From 541b5a32bd2f6626a7ce71253cc6110b725cae26 Mon Sep 17 00:00:00 2001 From: Samir Romdhani Date: Thu, 17 Aug 2023 16:43:36 +0200 Subject: [PATCH 1/2] fix deprecating set-output command in sonarcloud-analysis manifests yaml Signed-off-by: Samir Romdhani --- .github/workflows/sonarcloud-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sonarcloud-analysis.yml b/.github/workflows/sonarcloud-analysis.yml index 1b0ca65c6..03a3355cc 100644 --- a/.github/workflows/sonarcloud-analysis.yml +++ b/.github/workflows/sonarcloud-analysis.yml @@ -71,9 +71,9 @@ jobs: - name: Set Common Sonar Variables id: sonar_env run: | - echo "##[set-output name=sonar_opts;]$(echo -Dsonar.host.url=https://sonarcloud.io \ + echo "sonar_opts=-Dsonar.host.url=https://sonarcloud.io \ -Dsonar.projectKey=com-pas_compas-sct \ - -Dsonar.organization=com-pas )" + -Dsonar.organization=com-pas" >> $GITHUB_OUTPUT - name: Create custom Maven Settings.xml uses: whelk-io/maven-settings-xml-action@v21 with: From c13fce61ca2b27a42539b0d711319fae272f4b9e Mon Sep 17 00:00:00 2001 From: Samir Romdhani Date: Mon, 21 Aug 2023 14:17:22 +0200 Subject: [PATCH 2/2] refactor(#110): Create interface for Services and replace static methods with instance methods MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit closes #110 BREAKING CHANGE: 💥 in sct-commons: The services which provide static methods are moved from scl to commons package. Now those services implements interfaces, no static methods. Expect for PrivateService which is an UtilityClass is renamed to PrivateUtils and moved from scl to util package. Signed-off-by: Samir Romdhani refactor(#110): give PrivateService the new name PrivateUtils and change the package from scl to util. Changing the name of PrivateService to PrivateUtils and move it from scl to util package , closes #110 refactor(#110): update SclAutomationService Signed-off-by: Samir Romdhani refactor(#110): check review part1 use @RequiredArgsConstructor, instead of @NoArgsConstructor. use Camel case for PrivateLinkedToStds Signed-off-by: Samir Romdhani refactor(#110): check review part2 [use mockito properly] Remove unused test package. Use latest version of mockito. Fix related to version 5.4.0 Signed-off-by: Samir Romdhani refactor(#110): review part3 [naming] remove prefix 'I' and add suffix 'Editor' The interfaces are moved from scl to api package. add package doc Signed-off-by: Samir Romdhani refactor(#110): review part4 [seperate SclService features ] SclEditor (interface) spec are reduced by adding ReadOnly and Write One Signed-off-by: Samir Romdhani refactor(#110): sonar review Signed-off-by: Samir Romdhani docs(#110): update demo project and quickstart page Signed-off-by: Samir Romdhani --- docs/QUICK_START.md | 29 +- docs/examples/example-app/pom.xml | 10 +- .../compas/sct/examples/SctAppExample.java | 19 +- .../sct/examples/SctAppExampleTest.java | 40 +- pom.xml | 13 + sct-app/pom.xml | 8 + .../compas/sct/app/SclAutomationService.java | 25 +- .../SclAutomationServiceIntegrationTest.java | 167 +++++ .../SclAutomationServiceTest.java | 237 ++++--- sct-commons/pom.xml | 15 - .../sct/commons/{scl => }/ExtRefService.java | 284 ++++---- .../sct/commons/{scl => }/HmiService.java | 18 +- .../compas/sct/commons/SclEditorService.java | 238 +++++++ .../commons/SclElementsProviderService.java | 115 +++ .../commons/{scl => }/SubstationService.java | 44 +- .../compas/sct/commons/api/ExtRefEditor.java | 115 +++ .../compas/sct/commons/api/HmiEditor.java | 26 + .../compas/sct/commons/api/SclEditor.java | 172 +++++ .../sct/commons/api/SclElementsProvider.java | 109 +++ .../sct/commons/api/SubstationEditor.java | 32 + .../compas/sct/commons/api/package-info.java | 8 + .../sct/commons/dto/PrivateLinkedToStds.java | 14 + .../compas/sct/commons/scl/SclService.java | 606 ---------------- .../commons/scl/ied/AccessPointAdapter.java | 2 +- .../sct/commons/scl/ied/IEDAdapter.java | 8 +- .../sct/commons/scl/ied/InputsAdapter.java | 8 +- .../sct/commons/scl/ied/LN0Adapter.java | 4 +- .../sct/commons/util/FcdaCsvHelper.java | 4 +- .../PrivateUtils.java} | 49 +- .../model/NamespaceConfigurationTest.java | 4 +- .../commons/{scl => }/ExtRefServiceTest.java | 222 +++++- .../sct/commons/{scl => }/HmiServiceTest.java | 23 +- ...iceTest.java => SclEditorServiceTest.java} | 669 ++---------------- .../SclElementsProviderServiceTest.java | 343 +++++++++ .../{scl => }/SubstationServiceTest.java | 25 +- .../dto/ControlBlockNetworkSettingsTest.java | 4 +- .../sct/commons/scl/ied/IEDAdapterTest.java | 6 +- .../sct/commons/scl/ied/LN0AdapterTest.java | 3 +- .../scl/sstation/LNodeAdapterTest.java | 6 +- .../PrivateUtilsTest.java} | 144 ++-- 40 files changed, 2100 insertions(+), 1768 deletions(-) create mode 100644 sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java rename sct-commons/src/main/java/org/lfenergy/compas/sct/commons/{scl => }/ExtRefService.java (72%) rename sct-commons/src/main/java/org/lfenergy/compas/sct/commons/{scl => }/HmiService.java (51%) create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SclEditorService.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SclElementsProviderService.java rename sct-commons/src/main/java/org/lfenergy/compas/sct/commons/{scl => }/SubstationService.java (61%) create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ExtRefEditor.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/HmiEditor.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SclEditor.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SclElementsProvider.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SubstationEditor.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/package-info.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/PrivateLinkedToStds.java delete mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclService.java rename sct-commons/src/main/java/org/lfenergy/compas/sct/commons/{scl/PrivateService.java => util/PrivateUtils.java} (89%) rename sct-commons/src/test/java/org/lfenergy/compas/sct/commons/{scl => }/ExtRefServiceTest.java (82%) rename sct-commons/src/test/java/org/lfenergy/compas/sct/commons/{scl => }/HmiServiceTest.java (93%) rename sct-commons/src/test/java/org/lfenergy/compas/sct/commons/{scl/SclServiceTest.java => SclEditorServiceTest.java} (50%) create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SclElementsProviderServiceTest.java rename sct-commons/src/test/java/org/lfenergy/compas/sct/commons/{scl => }/SubstationServiceTest.java (79%) rename sct-commons/src/test/java/org/lfenergy/compas/sct/commons/{scl/PrivateServiceTest.java => util/PrivateUtilsTest.java} (75%) diff --git a/docs/QUICK_START.md b/docs/QUICK_START.md index 550e5128b..8a441541f 100644 --- a/docs/QUICK_START.md +++ b/docs/QUICK_START.md @@ -1,4 +1,4 @@ - + # CoMPAS SCT (Substation Configuration Tool) @@ -17,13 +17,13 @@ First you need to add following dependencies to the pom.xml of your repository. org.lfenergy.compas sct-commons - 0.1.0 + 0.2.12 org.lfenergy.compas sct-app - 0.1.0 + 0.2.12 ``` Actually there are 4 packages available: @@ -37,15 +37,20 @@ Actually there are 4 packages available: Now that you have your **compas-sct** dependency set, you can start communicating with Commons SCT services. **sct-commons** provides a collection of services to help you build SCL files for a range of use cases. + Following services provides needed functions compliant with IEC 61850 : -1. **SclService** -2. **SubstationService** +1. **SclEditorService** +2. **SclElementsProviderService** +3. **SubstationService** +4. **ExtRefService** +5. **HmiService** Let's start with a simple **SclService** call ```java -var scl = SclService.initScl(Optional.empty(), "1.0", "1.0"); +SclEditor sclEditorService = new SclEditorService(); +SCL scl = sclEditorService.initScl(UUID.randomUUID(), "1.0", "1.0"); marshaller.marshal(scl.getCurrentElem(), System.out); ``` @@ -78,11 +83,15 @@ Start it by using existing files of type `SSD` and `STD` and running the following : ```java -// ssd : SSD -// std : STD +// ssd : SCL object represent an SSD file +// std : SCL object represent an STD file +SclEditor sclService = new SclEditorService(); +SubstationEditor substationService = new SubstationService(); HeaderDTO headerDTO = new HeaderDTO(UUID.randomUUID(), "1.0", "1.0"); -var scl = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std)); -marshaller.marshal(scl.getCurrentElem(), System.out); + +SclAutomationService sclAutomationService = new SclAutomationService(sclService, substationService); +SCL scl = sclAutomationService.createSCD(ssd, headerDTO, List.of(std)); +marshaller.marshal(scl, System.out); ``` When the command completes, it prints XML output representing completed **SCL** file. Its structure resembles the following: diff --git a/docs/examples/example-app/pom.xml b/docs/examples/example-app/pom.xml index 52bf33115..d255c6df7 100644 --- a/docs/examples/example-app/pom.xml +++ b/docs/examples/example-app/pom.xml @@ -18,9 +18,9 @@ SPDX-License-Identifier: Apache-2.0 UTF-8 - 11 - 11 - 11 + 17 + 17 + 17 @@ -44,13 +44,13 @@ SPDX-License-Identifier: Apache-2.0 org.lfenergy.compas sct-commons - 0.1.0 + 0.2.12 org.lfenergy.compas sct-app - 0.1.0 + 0.2.12 org.junit.jupiter diff --git a/docs/examples/example-app/src/main/java/org/lfenergy/compas/sct/examples/SctAppExample.java b/docs/examples/example-app/src/main/java/org/lfenergy/compas/sct/examples/SctAppExample.java index b0c2bbfcf..63d4f4797 100644 --- a/docs/examples/example-app/src/main/java/org/lfenergy/compas/sct/examples/SctAppExample.java +++ b/docs/examples/example-app/src/main/java/org/lfenergy/compas/sct/examples/SctAppExample.java @@ -1,32 +1,33 @@ -// SPDX-FileCopyrightText: 2022 RTE FRANCE +// SPDX-FileCopyrightText: 2022 2023 RTE FRANCE // // SPDX-License-Identifier: Apache-2.0 package org.lfenergy.compas.sct.examples; import org.lfenergy.compas.scl2007b4.model.SCL; -import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; -import org.lfenergy.compas.sct.commons.scl.SclService; +import org.lfenergy.compas.sct.commons.SclEditorService; +import org.lfenergy.compas.sct.commons.api.SclEditor; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; -import java.util.Optional; import java.util.UUID; public class SctAppExample { + private static final SclEditor sclEditor = new SclEditorService(); + public static void main( String[] args ) throws JAXBException { - initSclWithSclService(Optional.empty(), "1.0", "1.0"); + initSclWithSclService(UUID.randomUUID(), "1.0", "1.0"); } - public static SclRootAdapter initSclWithSclService(Optional hId, String hVersion, String hRevision) throws JAXBException { - SclRootAdapter scl = SclService.initScl(hId, hVersion, hRevision); - marshaller.marshal(scl.getCurrentElem(), System.out); + public static SCL initSclWithSclService(UUID hId, String hVersion, String hRevision) throws JAXBException { + SCL scl = sclEditor.initScl(hId, hVersion, hRevision); + marshaller.marshal(scl, System.out); return scl; } - private static Marshaller marshaller; + private static final Marshaller marshaller; static{ try { JAXBContext context = JAXBContext.newInstance(SCL.class); diff --git a/docs/examples/example-app/src/test/java/org/lfenergy/compas/sct/examples/SctAppExampleTest.java b/docs/examples/example-app/src/test/java/org/lfenergy/compas/sct/examples/SctAppExampleTest.java index d2fbca3f1..6dc504830 100644 --- a/docs/examples/example-app/src/test/java/org/lfenergy/compas/sct/examples/SctAppExampleTest.java +++ b/docs/examples/example-app/src/test/java/org/lfenergy/compas/sct/examples/SctAppExampleTest.java @@ -10,38 +10,36 @@ import javax.xml.bind.JAXBException; import java.util.List; -import java.util.Optional; import java.util.UUID; -import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; -public class SctAppExampleTest { +class SctAppExampleTest { @Test - public void initSclWithSclServiceTest() throws JAXBException { + void initSclWithSclServiceTest() throws JAXBException { // Given : Header attributes - Optional headerId = Optional.of(UUID.randomUUID()); + UUID headerId = UUID.randomUUID(); String headerVersion = SclRootAdapter.VERSION; String headerRevision = SclRootAdapter.REVISION; // When: Sct Service - SclRootAdapter scl = SctAppExample - .initSclWithSclService(headerId, headerVersion, headerRevision); + SCL scl = SctAppExample.initSclWithSclService(headerId, headerVersion, headerRevision); // Then - assertNotNull(scl.getCurrentElem().getHeader()); - assertEquals(headerId.get().toString(), scl.getCurrentElem().getHeader().getId()); - assertEquals(headerVersion, scl.getCurrentElem().getHeader().getVersion()); - assertEquals(headerRevision, scl.getCurrentElem().getHeader().getRevision()); - THeader.History history = scl.getCurrentElem().getHeader().getHistory(); - List substations = scl.getCurrentElem().getSubstation(); - TCommunication communication = scl.getCurrentElem().getCommunication(); - List iedList = scl.getCurrentElem().getIED(); - TDataTypeTemplates dataTypeTemplates = scl.getCurrentElem().getDataTypeTemplates(); - assertNull(history); - assertEquals(0, substations.size()); - assertNull(communication); - assertEquals(0, iedList.size()); - assertNull(dataTypeTemplates); + assertThat(scl.getHeader()).isNotNull(); + assertThat(scl.getHeader().getId()).isEqualTo(headerId.toString()); + assertThat(scl.getHeader().getVersion()).isEqualTo(headerVersion); + assertThat(scl.getHeader().getRevision()).isEqualTo(headerRevision); + THeader.History history = scl.getHeader().getHistory(); + List substations = scl.getSubstation(); + TCommunication communication = scl.getCommunication(); + List iedList = scl.getIED(); + TDataTypeTemplates dataTypeTemplates = scl.getDataTypeTemplates(); + assertThat(history).isNull(); + assertThat(substations).isEmpty(); + assertThat(communication).isNull(); + assertThat(iedList).isEmpty(); + assertThat(dataTypeTemplates).isNull(); } } diff --git a/pom.xml b/pom.xml index 8adfb6c6a..65e41b5df 100644 --- a/pom.xml +++ b/pom.xml @@ -44,6 +44,7 @@ 1.4.5 3.22.0 1.18.24 + 5.5.0 2.13.4.1 @@ -78,6 +79,18 @@ ${junit-version} test + + org.mockito + mockito-core + ${mockito.version} + test + + + org.mockito + mockito-junit-jupiter + ${mockito.version} + test + org.lfenergy.compas.core scl-extension diff --git a/sct-app/pom.xml b/sct-app/pom.xml index f2ea2dca7..42afea091 100644 --- a/sct-app/pom.xml +++ b/sct-app/pom.xml @@ -58,6 +58,14 @@ org.assertj assertj-core + + org.mockito + mockito-core + + + org.mockito + mockito-junit-jupiter + diff --git a/sct-app/src/main/java/org/lfenergy/compas/sct/app/SclAutomationService.java b/sct-app/src/main/java/org/lfenergy/compas/sct/app/SclAutomationService.java index 234f86698..9046f6966 100644 --- a/sct-app/src/main/java/org/lfenergy/compas/sct/app/SclAutomationService.java +++ b/sct-app/src/main/java/org/lfenergy/compas/sct/app/SclAutomationService.java @@ -5,13 +5,14 @@ package org.lfenergy.compas.sct.app; import lombok.NonNull; +import lombok.RequiredArgsConstructor; import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.sct.commons.api.SclEditor; +import org.lfenergy.compas.sct.commons.api.SubstationEditor; import org.lfenergy.compas.sct.commons.dto.HeaderDTO; import org.lfenergy.compas.sct.commons.dto.SubNetworkDTO; import org.lfenergy.compas.sct.commons.dto.SubNetworkTypeDTO; import org.lfenergy.compas.sct.commons.exception.ScdException; -import org.lfenergy.compas.sct.commons.scl.SclService; -import org.lfenergy.compas.sct.commons.scl.SubstationService; import java.util.*; @@ -24,8 +25,12 @@ *
  • {@link SclAutomationService#createSCD(SCL, HeaderDTO, List) Adds all elements under the SCL object from given SSD and STD files} * */ +@RequiredArgsConstructor public class SclAutomationService { + private final SclEditor sclEditor; + private final SubstationEditor substationEditor; + /** * Possible Subnetwork and ConnectedAP names which should be used in generated SCD in order a have global coherence * Configuration based on used framework can be used to externalize this datas @@ -34,10 +39,6 @@ public class SclAutomationService { new SubNetworkTypeDTO("RSPACE_PROCESS_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString(), List.of("PROCESS_AP", "TOTO_AP_GE")), new SubNetworkTypeDTO("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString(), List.of("ADMIN_AP", "TATA_AP_EFFACEC"))); - private SclAutomationService() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } - /** * Create an SCD file from specified parameters, it calls all functions defined in the process one by one, every step * return an SCD file which will be used by the next step. @@ -47,15 +48,15 @@ private SclAutomationService() { * @return an SCD object * @throws ScdException */ - public static SCL createSCD(@NonNull SCL ssd, @NonNull HeaderDTO headerDTO, List stds) throws ScdException { - SCL scd = SclService.initScl(headerDTO.getId(), headerDTO.getVersion(), headerDTO.getRevision()); + public SCL createSCD(@NonNull SCL ssd, @NonNull HeaderDTO headerDTO, List stds) throws ScdException { + SCL scd = sclEditor.initScl(headerDTO.getId(), headerDTO.getVersion(), headerDTO.getRevision()); if (!headerDTO.getHistoryItems().isEmpty()) { HeaderDTO.HistoryItem hItem = headerDTO.getHistoryItems().get(0); - SclService.addHistoryItem(scd, hItem.getWho(), hItem.getWhat(), hItem.getWhy()); + sclEditor.addHistoryItem(scd, hItem.getWho(), hItem.getWhat(), hItem.getWhy()); } - SubstationService.addSubstation(scd, ssd); - SclService.importSTDElementsInSCD(scd, stds, SUB_NETWORK_TYPES); - SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scd); + substationEditor.addSubstation(scd, ssd); + sclEditor.importSTDElementsInSCD(scd, stds, SUB_NETWORK_TYPES); + sclEditor.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scd); return scd; } } diff --git a/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java b/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java new file mode 100644 index 000000000..1a10626f2 --- /dev/null +++ b/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java @@ -0,0 +1,167 @@ +// SPDX-FileCopyrightText: 2023 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.app; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.LN0; +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.sct.commons.SclEditorService; +import org.lfenergy.compas.sct.commons.SubstationService; +import org.lfenergy.compas.sct.commons.api.SclEditor; +import org.lfenergy.compas.sct.commons.api.SubstationEditor; +import org.lfenergy.compas.sct.commons.dto.HeaderDTO; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; +import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; + +class SclAutomationServiceIntegrationTest { + + private SclAutomationService sclAutomationService ; + private static final SclEditor sclEditor = new SclEditorService() ; + private static final SubstationEditor substationEditor = new SubstationService() ; + + private HeaderDTO headerDTO; + + @BeforeEach + void setUp() { + headerDTO = new HeaderDTO(); + headerDTO.setId(UUID.randomUUID()); + headerDTO.setRevision("hRevision"); + headerDTO.setVersion("hVersion"); + sclAutomationService = new SclAutomationService(sclEditor, substationEditor); + } + + @Test + void createSCD_should_return_generatedSCD() { + // Given + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd.xml"); + SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); + // When + SCL scd = sclAutomationService.createSCD(ssd, headerDTO, List.of(std)); + // Then + assertNotNull(scd.getHeader().getId()); + assertNull(scd.getHeader().getHistory()); + assertEquals(1, scd.getSubstation().size()); + assertEquals(1, scd.getIED().size()); + assertNotNull(scd.getDataTypeTemplates()); + assertEquals(2, scd.getCommunication().getSubNetwork().size()); + assertIsMarshallable(scd); + } + + @Test + void createSCD_With_HItem() { + // Given + HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); + historyItem.setWhat("what"); + historyItem.setWho("me"); + historyItem.setWhy("because"); + headerDTO.getHistoryItems().add(historyItem); + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); + SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); + SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml"); + SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml"); + // When + SCL scd = sclAutomationService.createSCD(ssd, headerDTO, List.of(std1, std2, std3)); + // Then + assertNotNull(scd.getHeader().getId()); + assertEquals(1, scd.getHeader().getHistory().getHitem().size()); + assertEquals(1, scd.getSubstation().size()); + assertIsMarshallable(scd); + } + + @Test + void createSCD_With_HItems() { + // Given + HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); + historyItem.setWhat("what"); + historyItem.setWho("me"); + historyItem.setWhy("because"); + HeaderDTO.HistoryItem historyItemBis = new HeaderDTO.HistoryItem(); + historyItemBis.setWhat("what Bis"); + historyItemBis.setWho("me bis"); + historyItemBis.setWhy("because bis"); + headerDTO.getHistoryItems().addAll(Arrays.asList(historyItem, historyItemBis)); + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); + SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); + SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml"); + SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml"); + // When + SCL scd = sclAutomationService.createSCD(ssd, headerDTO, List.of(std1, std2, std3)); + // Then + assertNotNull(scd.getHeader().getId()); + assertEquals(1, scd.getHeader().getHistory().getHitem().size()); + assertEquals("what", scd.getHeader().getHistory().getHitem().get(0).getWhat()); + assertIsMarshallable(scd); + } + + @Test + void createSCD_SSD_Without_Substation() { + // Given + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml"); + // When & Then + List stdListEmpty = List.of(); + assertThrows(ScdException.class, + () -> sclAutomationService.createSCD(ssd, headerDTO, stdListEmpty)); + } + + @Test + void createSCD_should_throw_exception_when_null_ssd() { + // Given + HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); + historyItem.setWhat("what"); + historyItem.setWho("me"); + historyItem.setWhy("because"); + headerDTO.getHistoryItems().add(historyItem); + SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); + List stdList = List.of(std1); + + // When & Then + assertThrows(NullPointerException.class, () -> sclAutomationService.createSCD(null, headerDTO, stdList)); + } + + @Test + void createSCD_should_throw_exception_when_null_headerDTO() { + // Given + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); + SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); + List stdList = List.of(std1); + + // When & Then + assertThrows(NullPointerException.class, () -> sclAutomationService.createSCD(ssd, null, stdList)); + } + + @Test + void createSCD_should_delete_ControlBlocks_DataSet_and_ExtRef_src_attributes() { + // Given + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/ssd.xml"); + SCL std = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml"); + // When + SCL scd = sclAutomationService.createSCD(ssd, headerDTO, List.of(std)); + // Then + LN0 ln0 = new SclRootAdapter(scd).streamIEDAdapters() + .findFirst() + .map(iedAdapter -> iedAdapter.findLDeviceAdapterByLdInst("lDeviceInst1").orElseThrow()) + .map(LDeviceAdapter::getLN0Adapter) + .map(SclElementAdapter::getCurrentElem) + .orElseThrow(() -> new RuntimeException("Test shouldn't fail here, please check your XML input file")); + + assertThat(ln0.getDataSet()).isEmpty(); + assertThat(ln0.getInputs().getExtRef()).hasSize(2); + assertFalse(ln0.getInputs().getExtRef().get(0).isSetSrcLDInst()); + assertIsMarshallable(scd); + } + +} diff --git a/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceTest.java b/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceTest.java index 1feb4f25e..f9e64e100 100644 --- a/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceTest.java +++ b/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceTest.java @@ -1,173 +1,192 @@ -// SPDX-FileCopyrightText: 2021 RTE FRANCE +// SPDX-FileCopyrightText: 2023 RTE FRANCE // // SPDX-License-Identifier: Apache-2.0 package org.lfenergy.compas.sct.app; +import org.apache.commons.beanutils.BeanUtils; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.lfenergy.compas.scl2007b4.model.LN0; +import org.junit.jupiter.api.extension.ExtendWith; import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.scl2007b4.model.THeader; +import org.lfenergy.compas.sct.commons.api.SclEditor; +import org.lfenergy.compas.sct.commons.api.SubstationEditor; import org.lfenergy.compas.sct.commons.dto.HeaderDTO; import org.lfenergy.compas.sct.commons.exception.ScdException; -import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; -import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; -import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; -import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; -import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.util.Arrays; import java.util.List; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; +@ExtendWith(MockitoExtension.class) class SclAutomationServiceTest { + @InjectMocks + private SclAutomationService sclAutomationService ; + @Mock + private SclEditor sclEditor; + @Mock + private SubstationEditor substationEditor; + + public static final short RELEASE = 4; + public static final String REVISION = "B"; + public static final String VERSION = "2007"; + private SCL scl; private HeaderDTO headerDTO; @BeforeEach - void init() { + void setUp() { + scl = new SCL(); + scl.setRelease(RELEASE); + scl.setVersion(VERSION); + scl.setRevision(REVISION); + THeader header = new THeader(); + header.setId(UUID.randomUUID().toString()); + scl.setHeader(header); headerDTO = new HeaderDTO(); headerDTO.setId(UUID.randomUUID()); - headerDTO.setRevision("hRevision"); - headerDTO.setVersion("hVersion"); + headerDTO.setRevision("Revision"); + headerDTO.setVersion("Version"); } @Test - void createSCD_should_return_generatedSCD() { + void createSCD_without_headerHistory_should_return_generatedSCD() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { // Given - SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd.xml"); - SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); + SCL ssd = (SCL) BeanUtils.cloneBean(scl); + SCL std = (SCL) BeanUtils.cloneBean(scl); + Mockito.when(sclEditor.initScl(any(UUID.class), anyString(), anyString())).thenReturn((SCL) BeanUtils.cloneBean(scl)); // When - SCL scd = SclAutomationService.createSCD(ssd, headerDTO, List.of(std)); + SCL scd = sclAutomationService.createSCD(ssd, headerDTO, List.of(std)); // Then - assertNotNull(scd.getHeader().getId()); - assertNull(scd.getHeader().getHistory()); - assertEquals(1, scd.getSubstation().size()); - assertEquals(1, scd.getIED().size()); - assertNotNull(scd.getDataTypeTemplates()); - assertEquals(2, scd.getCommunication().getSubNetwork().size()); + assertThat(scd.getHeader()).isNotNull(); + assertThat(scd.getHeader().getHistory()).isNull(); + assertThat(scd.getDataTypeTemplates()).isNull(); + assertThat(scd.getCommunication()).isNull(); + assertThat(scd.getSubstation()).isEmpty(); + assertThat(scd.getIED()).isEmpty(); assertIsMarshallable(scd); + verify(sclEditor, times(1)).initScl(headerDTO.getId(), headerDTO.getVersion(), headerDTO.getRevision()); + verify(sclEditor, times(0)).addHistoryItem(any(SCL.class), anyString(), anyString(), anyString()); + verify(substationEditor, times(1)).addSubstation(any(SCL.class), any(SCL.class)); + verify(sclEditor, times(1)).importSTDElementsInSCD(any(SCL.class), anyList(), anyList()); + verify(sclEditor, times(1)).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class)); } @Test - void createSCD_With_HItem() { + void createSCD_with_headerHistory_should_return_generatedSCD() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { // Given + SCL ssd = (SCL) BeanUtils.cloneBean(scl); + SCL std = (SCL) BeanUtils.cloneBean(scl); HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); - historyItem.setWhat("what"); - historyItem.setWho("me"); - historyItem.setWhy("because"); + historyItem.setWhat("test"); + historyItem.setWho("name"); + historyItem.setWhy("test"); headerDTO.getHistoryItems().add(historyItem); - SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); - SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); - SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml"); - SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml"); + when(sclEditor.initScl(any(UUID.class), anyString(), anyString())).thenReturn((SCL) BeanUtils.cloneBean(scl)); + doNothing().when(sclEditor).addHistoryItem(any(SCL.class), anyString(), anyString(), anyString()); // When - SCL scd = SclAutomationService.createSCD(ssd, headerDTO, List.of(std1, std2, std3)); + SCL scd = sclAutomationService.createSCD(ssd, headerDTO, List.of(std)); // Then - assertNotNull(scd.getHeader().getId()); - assertEquals(1, scd.getHeader().getHistory().getHitem().size()); - assertEquals(1, scd.getSubstation().size()); + assertThat(scd.getHeader()).isNotNull(); + assertThat(scd.getHeader().getHistory()).isNull(); + assertThat(scd.getDataTypeTemplates()).isNull(); + assertThat(scd.getCommunication()).isNull(); + assertThat(scd.getSubstation()).isEmpty(); + assertThat(scd.getIED()).isEmpty(); assertIsMarshallable(scd); + verify(sclEditor, times(1)).initScl(headerDTO.getId(), headerDTO.getVersion(), headerDTO.getRevision()); + verify(sclEditor, times(1)).addHistoryItem(any(SCL.class), eq(historyItem.getWho()), eq(historyItem.getWhat()), eq(historyItem.getWhy())); + verify(substationEditor, times(1)).addSubstation(any(SCL.class), any(SCL.class)); + verify(sclEditor, times(1)).importSTDElementsInSCD(any(SCL.class), anyList(), anyList()); + verify(sclEditor, times(1)).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class)); } @Test - void createSCD_With_HItems() { + void createSCD_should_throw_exception_when_sclEditor_initScl_Fail() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { // Given - HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); - historyItem.setWhat("what"); - historyItem.setWho("me"); - historyItem.setWhy("because"); - HeaderDTO.HistoryItem historyItemBis = new HeaderDTO.HistoryItem(); - historyItemBis.setWhat("what Bis"); - historyItemBis.setWho("me bis"); - historyItemBis.setWhy("because bis"); - headerDTO.getHistoryItems().addAll(Arrays.asList(historyItem, historyItemBis)); - SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); - SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); - SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml"); - SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml"); - // When - SCL scd = SclAutomationService.createSCD(ssd, headerDTO, List.of(std1, std2, std3)); - // Then - assertNotNull(scd.getHeader().getId()); - assertEquals(1, scd.getHeader().getHistory().getHitem().size()); - assertEquals("what", scd.getHeader().getHistory().getHitem().get(0).getWhat()); - assertIsMarshallable(scd); + SCL ssd = (SCL) BeanUtils.cloneBean(scl); + SCL std = (SCL) BeanUtils.cloneBean(scl); + doThrow(new ScdException("initScl fail")).when(sclEditor).initScl(any(UUID.class), anyString(), anyString()); + // When Then + assertThatThrownBy(() -> sclAutomationService.createSCD(ssd, headerDTO, List.of(std))) + .isInstanceOf(ScdException.class) + .hasMessage("initScl fail"); } @Test - void createSCD_SSD_Without_Substation() { + void createSCD_should_throw_exception_when_sclEditor_addHistoryItem_Fail() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { // Given - SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml"); - // When & Then - List stdListEmpty = List.of(); - assertThrows(ScdException.class, - () -> SclAutomationService.createSCD(ssd, headerDTO, stdListEmpty)); + SCL ssd = (SCL) BeanUtils.cloneBean(scl); + SCL std = (SCL) BeanUtils.cloneBean(scl); + headerDTO.getHistoryItems().add(new HeaderDTO.HistoryItem()); + when(sclEditor.initScl(any(UUID.class), anyString(), anyString())).thenReturn((SCL) BeanUtils.cloneBean(scl)); + doThrow(new ScdException("addHistoryItem fail")).when(sclEditor).addHistoryItem(any(SCL.class), any(), any(), any()); + // When Then + assertThatThrownBy(() -> sclAutomationService.createSCD(ssd, headerDTO, List.of(std))) + .isInstanceOf(ScdException.class) + .hasMessage("addHistoryItem fail"); } @Test - void createSCD_should_throw_exception_when_null_ssd() { + void createSCD_should_throw_exception_when_substationEditor_addSubstation_Fail() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { // Given - HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); - historyItem.setWhat("what"); - historyItem.setWho("me"); - historyItem.setWhy("because"); - headerDTO.getHistoryItems().add(historyItem); - SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); - List stdList = List.of(std1); - - // When & Then - assertThrows(NullPointerException.class, () -> SclAutomationService.createSCD(null, headerDTO, stdList)); + SCL ssd = (SCL) BeanUtils.cloneBean(scl); + SCL std = (SCL) BeanUtils.cloneBean(scl); + headerDTO.getHistoryItems().add(new HeaderDTO.HistoryItem()); + when(sclEditor.initScl(any(UUID.class), anyString(), anyString())).thenReturn((SCL) BeanUtils.cloneBean(scl)); + doNothing().when(sclEditor).addHistoryItem(any(SCL.class), any(), any(), any()); + doThrow(new ScdException("addSubstation fail")).when(substationEditor).addSubstation(any(SCL.class), any(SCL.class)); + // When Then + assertThatThrownBy(() -> sclAutomationService.createSCD(ssd, headerDTO, List.of(std))) + .isInstanceOf(ScdException.class) + .hasMessage("addSubstation fail"); } @Test - void createSCD_should_throw_exception_when_null_headerDTO() { + void createSCD_should_throw_exception_when_sclEditor_importSTDElementsInSCD_Fail() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { // Given - SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); - SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); - List stdList = List.of(std1); - - // When & Then - assertThrows(NullPointerException.class, () -> SclAutomationService.createSCD(ssd, null, stdList)); + SCL ssd = (SCL) BeanUtils.cloneBean(scl); + SCL std = (SCL) BeanUtils.cloneBean(scl); + headerDTO.getHistoryItems().add(new HeaderDTO.HistoryItem()); + when(sclEditor.initScl(any(UUID.class), anyString(), anyString())).thenReturn((SCL) BeanUtils.cloneBean(scl)); + doNothing().when(sclEditor).addHistoryItem(any(SCL.class), any(), any(), any()); + doNothing().when(substationEditor).addSubstation(any(SCL.class), any(SCL.class)); + doThrow(new ScdException("importSTDElementsInSCD fail")) + .when(sclEditor).importSTDElementsInSCD(any(SCL.class), anyList(), anyList()); + // When Then + assertThatThrownBy(() -> sclAutomationService.createSCD(ssd, headerDTO, List.of(std))) + .isInstanceOf(ScdException.class) + .hasMessage("importSTDElementsInSCD fail"); } @Test - void createSCD_should_delete_ControlBlocks_DataSet_and_ExtRef_src_attributes() { + void createSCD_should_throw_exception_when_sclEditor_removeAllControlBlocksAndDatasetsAndExtRefSrcBindings_Fail() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException { // Given - SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/ssd.xml"); - SCL std = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml"); - // When - SCL scd = SclAutomationService.createSCD(ssd, headerDTO, List.of(std)); - // Then - LN0 ln0 = new SclRootAdapter(scd).streamIEDAdapters() - .findFirst() - .map(iedAdapter -> iedAdapter.findLDeviceAdapterByLdInst("lDeviceInst1").orElseThrow()) - .map(LDeviceAdapter::getLN0Adapter) - .map(SclElementAdapter::getCurrentElem) - .orElseThrow(() -> new RuntimeException("Test shouldn't fail here, please check your XML input file")); - - assertThat(ln0.getDataSet()).isEmpty(); - assertThat(ln0.getInputs().getExtRef()).hasSize(2); - assertFalse(ln0.getInputs().getExtRef().get(0).isSetSrcLDInst()); - assertIsMarshallable(scd); + SCL ssd = (SCL) BeanUtils.cloneBean(scl); + SCL std = (SCL) BeanUtils.cloneBean(scl); + headerDTO.getHistoryItems().add(new HeaderDTO.HistoryItem()); + when(sclEditor.initScl(any(UUID.class), anyString(), anyString())).thenReturn((SCL) BeanUtils.cloneBean(scl)); + doNothing().when(sclEditor).addHistoryItem(any(SCL.class), any(), any(), any()); + doNothing().when(substationEditor).addSubstation(any(SCL.class), any(SCL.class)); + doNothing().when(sclEditor).importSTDElementsInSCD(any(SCL.class), anyList(), anyList()); + doThrow(new ScdException("removeAllControlBlocksAndDatasetsAndExtRefSrcBindings fail")) + .when(sclEditor).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class)); + // When Then + assertThatThrownBy(() -> sclAutomationService.createSCD(ssd, headerDTO, List.of(std))) + .isInstanceOf(ScdException.class) + .hasMessage("removeAllControlBlocksAndDatasetsAndExtRefSrcBindings fail"); } - @Test - void class_should_not_be_instantiable() { - // Given - Constructor[] constructors = SclAutomationService.class.getDeclaredConstructors(); - assertThat(constructors).hasSize(1); - Constructor constructor = constructors[0]; - constructor.setAccessible(true); - // When & Then - assertThatThrownBy(constructor::newInstance) - .isInstanceOf(InvocationTargetException.class) - .getCause().isInstanceOf(UnsupportedOperationException.class); - } } diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index c95154fb6..b91c97336 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -21,7 +21,6 @@ ${basedir}/${aggregate.report.dir} **/scl2007b4/**/* 5.7.1 - 4.9.0 @@ -70,28 +69,14 @@ junit-jupiter-params test - - org.hamcrest - hamcrest - 2.2 - test - org.mockito mockito-core - ${mockito.version} - test - - - org.mockito - mockito-inline - ${mockito.version} test org.mockito mockito-junit-jupiter - ${mockito.version} test diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ExtRefService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefService.java similarity index 72% rename from sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ExtRefService.java rename to sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefService.java index 00ccd1b23..1375e8854 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ExtRefService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefService.java @@ -2,43 +2,92 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl; +package org.lfenergy.compas.sct.commons; import org.apache.commons.lang3.StringUtils; +import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.api.ExtRefEditor; import org.lfenergy.compas.sct.commons.dto.*; +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.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.ied.*; import org.lfenergy.compas.sct.commons.util.*; -import org.lfenergy.compas.scl2007b4.model.SCL; -import org.lfenergy.compas.scl2007b4.model.TCompasICDHeader; -import org.lfenergy.compas.scl2007b4.model.TExtRef; -import org.lfenergy.compas.scl2007b4.model.TIED; -import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings; -import org.lfenergy.compas.sct.commons.dto.SclReportItem; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.*; import static org.lfenergy.compas.sct.commons.util.CommonConstants.*; import static org.lfenergy.compas.sct.commons.util.Utils.isExtRefFeedBySameControlBlock; -public final class ExtRefService { +public class ExtRefService implements ExtRefEditor { + private static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info"; - private static final String MESSAGE_MISSING_IED_NAME_PARAMETER = "IED.name parameter is missing"; + @Override + public void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws ScdException { + if (extRefInfo.getBindingInfo() == null || extRefInfo.getSignalInfo() == null) { + throw new ScdException("ExtRef Signal and/or Binding information are missing"); + } + String iedName = extRefInfo.getHolderIEDName(); + String ldInst = extRefInfo.getHolderLDInst(); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); + LDeviceAdapter lDeviceAdapter = iedAdapter.findLDeviceAdapterByLdInst(ldInst) + .orElseThrow(() -> new ScdException(String.format("Unknown LDevice (%s) in IED (%s)", ldInst, iedName))); + + AbstractLNAdapter abstractLNAdapter = AbstractLNAdapter.builder() + .withLDeviceAdapter(lDeviceAdapter) + .withLnClass(extRefInfo.getHolderLnClass()) + .withLnInst(extRefInfo.getHolderLnInst()) + .withLnPrefix(extRefInfo.getHolderLnPrefix()) + .build(); - private ExtRefService() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + abstractLNAdapter.updateExtRefBinders(extRefInfo); } - /** - * Updates iedName attribute of all ExtRefs in the Scd. - * - * @return list of encountered errors - */ - public static List updateAllExtRefIedNames(SCL scd) { + @Override + public TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws ScdException { + String iedName = extRefInfo.getHolderIEDName(); + String ldInst = extRefInfo.getHolderLDInst(); + String lnClass = extRefInfo.getHolderLnClass(); + String lnInst = extRefInfo.getHolderLnInst(); + String prefix = extRefInfo.getHolderLnPrefix(); + + ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); + if (signalInfo == null || !signalInfo.isValid()) { + throw new ScdException("Invalid or missing attributes in ExtRef signal info"); + } + ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo(); + if (bindingInfo == null || !bindingInfo.isValid()) { + throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); + } + if (bindingInfo.getIedName().equals(iedName) || TServiceType.POLL.equals(bindingInfo.getServiceType())) { + throw new ScdException("Internal binding can't have control block"); + } + ExtRefSourceInfo sourceInfo = extRefInfo.getSourceInfo(); + if (sourceInfo == null || !sourceInfo.isValid()) { + throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); + } + + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); + LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst); + AbstractLNAdapter anLNAdapter = AbstractLNAdapter.builder() + .withLDeviceAdapter(lDeviceAdapter) + .withLnClass(lnClass) + .withLnInst(lnInst) + .withLnPrefix(prefix) + .build(); + return anLNAdapter.updateExtRefSource(extRefInfo); + } + + @Override + public List updateAllExtRefIedNames(SCL scd) { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); List iedErrors = validateIed(sclRootAdapter); if (!iedErrors.isEmpty()) { @@ -62,13 +111,84 @@ public static List updateAllExtRefIedNames(SCL scd) { .flatMap(List::stream).toList(); } - private static List validateIed(SclRootAdapter sclRootAdapter) { + @Override + public List createDataSetAndControlBlocks(SCL scd) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + Stream lDeviceAdapters = sclRootAdapter.streamIEDAdapters().flatMap(IEDAdapter::streamLDeviceAdapters); + return createDataSetAndControlBlocks(lDeviceAdapters); + } + + @Override + public List createDataSetAndControlBlocks(SCL scd, String targetIedName) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(targetIedName); + return createDataSetAndControlBlocks(iedAdapter.streamLDeviceAdapters()); + + } + + @Override + public List createDataSetAndControlBlocks(SCL scd, String targetIedName, String targetLDeviceInst) { + if (StringUtils.isBlank(targetIedName)) { + throw new ScdException("IED.name parameter is missing"); + } + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(targetIedName); + LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(targetLDeviceInst); + return createDataSetAndControlBlocks(Stream.of(lDeviceAdapter)); + } + + private List createDataSetAndControlBlocks(Stream lDeviceAdapters) { + return lDeviceAdapters + .map(LDeviceAdapter::createDataSetAndControlBlocks) + .flatMap(List::stream) + .toList(); + } + + @Override + public List configureNetworkForAllControlBlocks(SCL scd, ControlBlockNetworkSettings controlBlockNetworkSettings, + RangesPerCbType rangesPerCbType) { + List sclReportItems = new ArrayList<>(); + sclReportItems.addAll(configureNetworkForControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType.gse(), ControlBlockEnum.GSE)); + sclReportItems.addAll(configureNetworkForControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType.sampledValue(), ControlBlockEnum.SAMPLED_VALUE)); + return sclReportItems; + } + + @Override + public List manageBindingForLDEPF(SCL scd, ILDEPFSettings settings) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + List sclReportItems = new ArrayList<>(); + sclRootAdapter.streamIEDAdapters() + .filter(iedAdapter -> !iedAdapter.getName().equals(IED_TEST_NAME)) + .map(iedAdapter -> iedAdapter.findLDeviceAdapterByLdInst(LDEVICE_LDEPF)) + .flatMap(Optional::stream) + .forEach(lDeviceAdapter -> + lDeviceAdapter.getExtRefBayReferenceForActifLDEPF(sclReportItems) + .forEach(extRefBayRef -> settings.getLDEPFSettingDataMatchExtRef(extRefBayRef.extRef()) + .ifPresent(lDPFSettingMatchingExtRef -> { + List iedSources = settings.getIedSources(sclRootAdapter, extRefBayRef.compasBay(), lDPFSettingMatchingExtRef); + if (iedSources.size() == 1) { + updateLDEPFExtRefBinding(extRefBayRef.extRef(), iedSources.get(0), lDPFSettingMatchingExtRef); + sclReportItems.addAll(updateLDEPFDos(lDeviceAdapter, extRefBayRef.extRef(), lDPFSettingMatchingExtRef)); + } else { + if (iedSources.size() > 1) { + sclReportItems.add(SclReportItem.warning(null, "There is more than one IED source to bind the signal " + + "/IED@name=" + extRefBayRef.iedName() + "/LDevice@inst=LDEPF/LN0" + + "/ExtRef@desc=" + extRefBayRef.extRef().getDesc())); + } + } + })) + ); + return sclReportItems; + + } + + private List validateIed(SclRootAdapter sclRootAdapter) { List iedErrors = new ArrayList<>(checkIedCompasIcdHeaderAttributes(sclRootAdapter)); iedErrors.addAll(checkIedUnityOfIcdSystemVersionUuid(sclRootAdapter)); return iedErrors; } - private static List checkIedCompasIcdHeaderAttributes(SclRootAdapter sclRootAdapter) { + private List checkIedCompasIcdHeaderAttributes(SclRootAdapter sclRootAdapter) { return sclRootAdapter.streamIEDAdapters() .map(iedAdapter -> { Optional compasPrivate = iedAdapter.getCompasICDHeader(); @@ -86,9 +206,9 @@ private static List checkIedCompasIcdHeaderAttributes(SclRootAdap .toList(); } - private static List checkIedUnityOfIcdSystemVersionUuid(SclRootAdapter sclRootAdapter) { + private List checkIedUnityOfIcdSystemVersionUuid(SclRootAdapter sclRootAdapter) { Map> systemVersionToIedList = sclRootAdapter.getCurrentElem().getIED().stream() - .collect(Collectors.groupingBy(ied -> PrivateService.extractCompasPrivate(ied, TCompasICDHeader.class) + .collect(Collectors.groupingBy(ied -> PrivateUtils.extractCompasPrivate(ied, TCompasICDHeader.class) .map(TCompasICDHeader::getICDSystemVersionUUID) .orElse(""))); @@ -104,81 +224,7 @@ private static List checkIedUnityOfIcdSystemVersionUuid(SclRootAd .toList(); } - /** - * Create All DataSet and ControlBlock in the SCL based on the ExtRef - * - * @param scd input SCD object. It could be modified by adding new DataSet and ControlBlocks - * @return list of encountered errors - */ - public static List createDataSetAndControlBlocks(SCL scd) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - Stream lDeviceAdapters = sclRootAdapter.streamIEDAdapters().flatMap(IEDAdapter::streamLDeviceAdapters); - return createDataSetAndControlBlocks(lDeviceAdapters); - } - - /** - * Create All DataSet and ControlBlock for the ExtRef in given IED - * - * @param scd input SCD object. The object will be modified with the new DataSet and ControlBlocks - * @param targetIedName the name of the IED where the ExtRef are - * @return list of encountered errors - */ - public static List createDataSetAndControlBlocks(SCL scd, String targetIedName) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(targetIedName); - return createDataSetAndControlBlocks(iedAdapter.streamLDeviceAdapters()); - - } - - /** - * Create All DataSet and ControlBlock for the ExtRef in this LDevice - * - * @param scd input SCD object. The object will be modified with the new DataSet and ControlBlocks - * @param targetIedName the name of the IED where the ExtRef are - * @param targetLDeviceInst the name of the LDevice where the ExtRef are - * @return list of encountered errors - */ - public static List createDataSetAndControlBlocks(SCL scd, String targetIedName, String targetLDeviceInst) { - if (StringUtils.isBlank(targetIedName)) { - throw new ScdException(MESSAGE_MISSING_IED_NAME_PARAMETER); - } - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(targetIedName); - LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(targetLDeviceInst); - return createDataSetAndControlBlocks(Stream.of(lDeviceAdapter)); - } - - private static List createDataSetAndControlBlocks(Stream lDeviceAdapters) { - return lDeviceAdapters - .map(LDeviceAdapter::createDataSetAndControlBlocks) - .flatMap(List::stream) - .toList(); - } - - /** - * Configure the network for all the ControlBlocks. - * Create (or update if already existing) these elements - * - 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") - * @return list of encountered errors - * @see Utils#macAddressToLong(String) for the expected MAC address format - * @see ControlBlockNetworkSettings - * @see ControlBlockNetworkSettings.RangesPerCbType - * @see ControlBlockNetworkSettings.NetworkRanges - */ - public static List configureNetworkForAllControlBlocks(SCL scd, ControlBlockNetworkSettings controlBlockNetworkSettings, - RangesPerCbType rangesPerCbType) { - List sclReportItems = new ArrayList<>(); - sclReportItems.addAll(configureNetworkForControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType.gse(), ControlBlockEnum.GSE)); - sclReportItems.addAll(configureNetworkForControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType.sampledValue(), ControlBlockEnum.SAMPLED_VALUE)); - return sclReportItems; - } - private static List configureNetworkForControlBlocks(SCL scd, ControlBlockNetworkSettings controlBlockNetworkSettings, + 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()); @@ -194,7 +240,7 @@ private static List configureNetworkForControlBlocks(SCL scd, Con .flatMap(Optional::stream) .toList(); } - private static Optional configureControlBlockNetwork(ControlBlockNetworkSettings controlBlockNetworkSettings, PrimitiveIterator.OfLong appIdIterator, Iterator macAddressIterator, ControlBlockAdapter controlBlockAdapter) { + private Optional configureControlBlockNetwork(ControlBlockNetworkSettings controlBlockNetworkSettings, PrimitiveIterator.OfLong appIdIterator, Iterator macAddressIterator, ControlBlockAdapter controlBlockAdapter) { SettingsOrError settingsOrError = controlBlockNetworkSettings.getNetworkSettings(controlBlockAdapter); if (settingsOrError.errorMessage() != null) { return Optional.of(controlBlockAdapter.buildFatalReportItem( @@ -236,41 +282,7 @@ public static List filterDuplicatedExtRefs(List tExtRefs) { return filteredList; } - /** - * ExtRef Binding For LDevice (inst=LDEPF) that matching LDEPF configuration - * @param scd SCL - * @param settings ILDEPFSettings - * @return list of encountered errors - */ - public static List manageBindingForLDEPF(SCL scd, ILDEPFSettings settings) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - List sclReportItems = new ArrayList<>(); - sclRootAdapter.streamIEDAdapters() - .filter(iedAdapter -> !iedAdapter.getName().equals(IED_TEST_NAME)) - .map(iedAdapter -> iedAdapter.findLDeviceAdapterByLdInst(LDEVICE_LDEPF)) - .flatMap(Optional::stream) - .forEach(lDeviceAdapter -> - lDeviceAdapter.getExtRefBayReferenceForActifLDEPF(sclReportItems) - .forEach(extRefBayRef -> settings.getLDEPFSettingDataMatchExtRef(extRefBayRef.extRef()) - .ifPresent(lDPFSettingMatchingExtRef -> { - List iedSources = settings.getIedSources(sclRootAdapter, extRefBayRef.compasBay(), lDPFSettingMatchingExtRef); - if (iedSources.size() == 1) { - updateLDEPFExtRefBinding(extRefBayRef.extRef(), iedSources.get(0), lDPFSettingMatchingExtRef); - sclReportItems.addAll(updateLDEPFDos(lDeviceAdapter, extRefBayRef.extRef(), lDPFSettingMatchingExtRef)); - } else { - if (iedSources.size() > 1) { - sclReportItems.add(SclReportItem.warning(null, "There is more than one IED source to bind the signal " + - "/IED@name=" + extRefBayRef.iedName() + "/LDevice@inst=LDEPF/LN0" + - "/ExtRef@desc=" + extRefBayRef.extRef().getDesc())); - } - } - })) - ); - return sclReportItems; - - } - - private static void updateLDEPFExtRefBinding(TExtRef extRef, TIED iedSource, LDEPFSettingData setting) { + private void updateLDEPFExtRefBinding(TExtRef extRef, TIED iedSource, LDEPFSettingData setting) { extRef.setIedName(iedSource.getName()); extRef.setLdInst(setting.getLdInst()); extRef.getLnClass().add(setting.getLnClass()); @@ -282,7 +294,7 @@ private static void updateLDEPFExtRefBinding(TExtRef extRef, TIED iedSource, LDE extRef.setDoName(doName); } - private static List updateLDEPFDos(LDeviceAdapter lDeviceAdapter, TExtRef extRef, LDEPFSettingData setting) { + private List updateLDEPFDos(LDeviceAdapter lDeviceAdapter, TExtRef extRef, LDEPFSettingData setting) { List sclReportItems = new ArrayList<>(); List doNameAndDaNameList = List.of( new DoNameAndDaName(CHNUM1_DO_NAME, DU_DA_NAME), @@ -307,7 +319,7 @@ private static List updateLDEPFDos(LDeviceAdapter lDeviceAdapter, return sclReportItems; } - private static Optional updateVal(AbstractLNAdapter lnAdapter, String doName, String daName, TExtRef extRef, LDEPFSettingData setting) { + private Optional updateVal(AbstractLNAdapter lnAdapter, String doName, String daName, TExtRef extRef, LDEPFSettingData setting) { String value = switch (daName) { case DU_DA_NAME -> setting.getChannelShortLabel(); case SETVAL_DA_NAME -> @@ -322,7 +334,7 @@ private static Optional updateVal(AbstractLNAdapter lnAdapter, private record DoNameAndDaName(String doName, String daName) { } - private static String computeDaiValue(AbstractLNAdapter lnAdapter, TExtRef extRef, String daName) { + private String computeDaiValue(AbstractLNAdapter lnAdapter, TExtRef extRef, String daName) { if (LN_PREFIX_B.equals(lnAdapter.getPrefix()) || LN_PREFIX_A.equals(lnAdapter.getPrefix())) { return extRef.getIedName() + extRef.getLdInst() + "/" + diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/HmiService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/HmiService.java similarity index 51% rename from sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/HmiService.java rename to sct-commons/src/main/java/org/lfenergy/compas/sct/commons/HmiService.java index 9b72b2544..ef9477aa8 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/HmiService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/HmiService.java @@ -2,26 +2,20 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl; +package org.lfenergy.compas.sct.commons; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TFCDA; +import org.lfenergy.compas.sct.commons.api.HmiEditor; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; import java.util.List; -public final class HmiService { +public class HmiService implements HmiEditor { - private HmiService() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } - - /** - * Create the DataSet and ReportControl Blocks for the HMI with the given FCDAs. - * - * @param fcdas List of FCDA for which we must create the DataSet and ReportControl Blocks - */ - public static void createAllHmiReportControlBlocks(SCL scd, List fcdas) { + @Override + public void createAllHmiReportControlBlocks(SCL scd, List fcdas) { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); sclRootAdapter.streamIEDAdapters() .flatMap(IEDAdapter::streamLDeviceAdapters) diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SclEditorService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SclEditorService.java new file mode 100644 index 000000000..f52cc3b27 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SclEditorService.java @@ -0,0 +1,238 @@ +// SPDX-FileCopyrightText: 2021 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons; + +import lombok.NonNull; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.Pair; +import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.api.SclEditor; +import org.lfenergy.compas.sct.commons.dto.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.scl.com.CommunicationAdapter; +import org.lfenergy.compas.sct.commons.scl.com.ConnectedAPAdapter; +import org.lfenergy.compas.sct.commons.scl.com.SubNetworkAdapter; +import org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter; +import org.lfenergy.compas.sct.commons.scl.dtt.LNodeTypeAdapter; +import org.lfenergy.compas.sct.commons.scl.header.HeaderAdapter; +import org.lfenergy.compas.sct.commons.scl.icd.IcdHeader; +import org.lfenergy.compas.sct.commons.scl.ied.*; +import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; +import org.lfenergy.compas.sct.commons.util.PrivateUtils; +import org.lfenergy.compas.sct.commons.util.Utils; + +import java.util.*; + +import static org.lfenergy.compas.sct.commons.util.CommonConstants.IED_TEST_NAME; +import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_ICDHEADER; + +@Slf4j +public class SclEditorService implements SclEditor { + + @Override + public SCL initScl(final UUID hId, final String hVersion, final String hRevision) throws ScdException { + SclRootAdapter scdAdapter = new SclRootAdapter(hId.toString(), hVersion, hRevision); + scdAdapter.addPrivate(PrivateUtils.createPrivate(TCompasSclFileType.SCD)); + return scdAdapter.getCurrentElem(); + } + + @Override + public void addHistoryItem(SCL scd, String who, String what, String why) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + HeaderAdapter headerAdapter = sclRootAdapter.getHeaderAdapter(); + headerAdapter.addHistoryItem(who, what, why); + } + + @Override + public void updateHeader(@NonNull SCL scd, @NonNull HeaderDTO headerDTO) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + HeaderAdapter headerAdapter = sclRootAdapter.getHeaderAdapter(); + boolean hUpdated = false; + String hVersion = headerDTO.getVersion(); + String hRevision = headerDTO.getRevision(); + if (hVersion != null && !hVersion.equals(headerAdapter.getHeaderVersion())) { + headerAdapter.updateVersion(hVersion); + hUpdated = true; + } + if (hRevision != null && !hRevision.equals(headerAdapter.getHeaderRevision())) { + headerAdapter.updateRevision(hRevision); + hUpdated = true; + } + if (hUpdated && !headerDTO.getHistoryItems().isEmpty()) { + headerAdapter.addHistoryItem( + headerDTO.getHistoryItems().get(0).getWho(), + headerDTO.getHistoryItems().get(0).getWhat(), + headerDTO.getHistoryItems().get(0).getWhy() + ); + } + } + + @Override + public void addIED(SCL scd, String iedName, SCL icd) throws ScdException { + new SclRootAdapter(scd).addIED(icd, iedName); + } + + @Override + public void addSubnetworks(SCL scd, List subNetworks, SCL icd) throws ScdException { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + CommunicationAdapter communicationAdapter; + if (!subNetworks.isEmpty()) { + communicationAdapter = sclRootAdapter.getCommunicationAdapter(true); + for (SubNetworkDTO subNetworkDTO : subNetworks) { + String snName = subNetworkDTO.getName(); + String snType = subNetworkDTO.getType(); + for (ConnectedApDTO accessPoint : subNetworkDTO.getConnectedAPs()) { + String iedName = accessPoint.iedName(); + String apName = accessPoint.apName(); + communicationAdapter.addSubnetwork(snName, snType, iedName, apName); + + Optional subNetworkAdapter = communicationAdapter.getSubnetworkByName(snName); + if (subNetworkAdapter.isPresent()) { + ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.get().getConnectedAPAdapter(iedName, apName); + connectedAPAdapter.copyAddressAndPhysConnFromIcd(icd); + } + } + } + } + } + + @Override + public void updateDAI(SCL scd, String iedName, String ldInst, DataAttributeRef dataAttributeRef) throws ScdException { + long startTime = System.nanoTime(); + log.info(Utils.entering()); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + DataTypeTemplateAdapter dttAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); + LNodeTypeAdapter lNodeTypeAdapter = dttAdapter.getLNodeTypeAdapterById(dataAttributeRef.getLnType()) + .orElseThrow(() -> new ScdException("Unknown LNodeType : " + dataAttributeRef.getLnType())); + lNodeTypeAdapter.check(dataAttributeRef.getDoName(), dataAttributeRef.getDaName()); + + if (TPredefinedBasicTypeEnum.OBJ_REF == dataAttributeRef.getBType()) { + Long sGroup = dataAttributeRef.getDaName().getDaiValues().keySet().stream().findFirst().orElse(-1L); + String val = sGroup < 0 ? null : dataAttributeRef.getDaName().getDaiValues().get(sGroup); + sclRootAdapter.checkObjRef(val); + } + + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); + LDeviceAdapter lDeviceAdapter = iedAdapter.findLDeviceAdapterByLdInst(ldInst) + .orElseThrow(() -> new ScdException(String.format("Unknown LDevice (%s) in IED (%s)", ldInst, iedName))); + + AbstractLNAdapter lnAdapter = AbstractLNAdapter.builder() + .withLDeviceAdapter(lDeviceAdapter) + .withLnClass(dataAttributeRef.getLnClass()) + .withLnInst(dataAttributeRef.getLnInst()) + .withLnPrefix(dataAttributeRef.getPrefix()) + .build(); + + if (TPredefinedCDCEnum.ING == dataAttributeRef.getCdc() || TPredefinedCDCEnum.ASG == dataAttributeRef.getCdc()) { + DAITracker daiTracker = new DAITracker(lnAdapter, dataAttributeRef.getDoName(), dataAttributeRef.getDaName()); + daiTracker.validateBoundedDAI(); + } + lnAdapter.updateDAI(dataAttributeRef); + log.info(Utils.leaving(startTime)); + } + + @Override + public void importSTDElementsInSCD(SCL scd, List stds, List subNetworkTypes) throws ScdException { + + //Check SCD and STD compatibilities + Map mapICDSystemVersionUuidAndSTDFile = PrivateUtils.createMapICDSystemVersionUuidAndSTDFile(stds); + PrivateUtils.checkSTDCorrespondanceWithLNodeCompasICDHeader(mapICDSystemVersionUuidAndSTDFile); + // List all Private and remove duplicated one with same iedName + // For each Private.ICDSystemVersionUUID and Private.iedName find STD File + List iedNamesUsed = new ArrayList<>(); + SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + PrivateUtils.streamIcdHeaders(scd) + .forEach(icdHeader -> { + if (!iedNamesUsed.contains(icdHeader.getIedName())) { + String iedName = icdHeader.getIedName(); + iedNamesUsed.add(iedName); + String icdSysVerUuid = icdHeader.getIcdSystemVersionUUID(); + if (!mapICDSystemVersionUuidAndSTDFile.containsKey(icdSysVerUuid)) + throw new ScdException("There is no STD file found corresponding to " + icdHeader); + // import /ied /dtt in Scd + SCL std = mapICDSystemVersionUuidAndSTDFile.get(icdSysVerUuid).stdList().get(0); + SclRootAdapter stdRootAdapter = new SclRootAdapter(std); + IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); + Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(COMPAS_ICDHEADER.getPrivateType()); + if (optionalTPrivate.isPresent() && optionalTPrivate.flatMap(PrivateUtils::extractCompasICDHeader).map(IcdHeader::new).get().equals(icdHeader)) { + PrivateUtils.copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(optionalTPrivate.get(), icdHeader.toTCompasICDHeader()); + } else throw new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED"); + scdRootAdapter.addIED(std, iedName); + + //import connectedAP and rename ConnectedAP/@iedName + TCommunication communication = stdRootAdapter.getCurrentElem().getCommunication(); + List subNetworkDTOSet = SubNetworkDTO.createDefaultSubnetwork(iedName, communication, subNetworkTypes); + addSubnetworks(scdRootAdapter.getCurrentElem(), subNetworkDTOSet, std); + } + }); + } + + @Override + public void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final SCL scl) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scl); + List lDeviceAdapters = sclRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters).toList(); + + // LN0 + lDeviceAdapters.stream() + .map(LDeviceAdapter::getLN0Adapter) + .forEach(ln0 -> { + ln0.removeAllControlBlocksAndDatasets(); + ln0.removeAllExtRefSourceBindings(); + }); + + // Other LN + lDeviceAdapters.stream() + .map(LDeviceAdapter::getLNAdapters).flatMap(List::stream) + .forEach(LNAdapter::removeAllControlBlocksAndDatasets); + } + + @Override + public List updateLDeviceStatus(SCL scd) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + SubstationAdapter substationAdapter = sclRootAdapter.getSubstationAdapter(); + final List> iedNameLdInstList = substationAdapter.getIedAndLDeviceNamesForLN0FromLNode(); + return sclRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters) + .map(LDeviceAdapter::getLN0Adapter) + .map(ln0Adapter -> ln0Adapter.updateLDeviceStatus(iedNameLdInstList)) + .flatMap(Optional::stream) + .toList(); + } + + @Override + public List analyzeDataGroups(SCL scd) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + return sclRootAdapter.streamIEDAdapters() + .map(iedAdapter -> { + List list = new ArrayList<>(); + list.addAll(iedAdapter.checkDataGroupCoherence()); + list.addAll(iedAdapter.checkBindingDataGroupCoherence()); + return list; + }).flatMap(Collection::stream).toList(); + } + + @Override + public List updateDoInRef(SCL scd) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + return sclRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters) + .map(LDeviceAdapter::getLN0Adapter) + .map(LN0Adapter::updateDoInRef) + .flatMap(List::stream) + .toList(); + } + + @Override + public List manageMonitoringLns(SCL scd) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + return sclRootAdapter.streamIEDAdapters() + .filter(iedAdapter -> !iedAdapter.getName().contains(IED_TEST_NAME)) + .map(IEDAdapter::manageMonitoringLns) + .flatMap(List::stream) + .toList(); + } +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SclElementsProviderService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SclElementsProviderService.java new file mode 100644 index 000000000..51c9f46d4 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SclElementsProviderService.java @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: 2021 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons; + +import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.api.SclElementsProvider; +import org.lfenergy.compas.sct.commons.dto.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.scl.com.CommunicationAdapter; +import org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter; +import org.lfenergy.compas.sct.commons.scl.dtt.EnumTypeAdapter; +import org.lfenergy.compas.sct.commons.scl.ied.*; + +import java.util.*; +import java.util.stream.Collectors; + +public class SclElementsProviderService implements SclElementsProvider { + + @Override + public List getSubnetwork(SCL scd) throws ScdException { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + CommunicationAdapter communicationAdapter = sclRootAdapter.getCommunicationAdapter(false); + return communicationAdapter.getSubNetworkAdapters().stream() + .map(SubNetworkDTO::from) + .toList(); + } + + @Override + public List getExtRefInfo(SCL scd, String iedName, String ldInst) throws ScdException { + LDeviceAdapter lDeviceAdapter = createLDeviceAdapter(scd, iedName, ldInst); + return lDeviceAdapter.getExtRefInfo(); + } + + @Override + public List getExtRefBinders(SCL scd, String iedName, String ldInst, String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException { + LDeviceAdapter lDeviceAdapter = createLDeviceAdapter(scd, iedName, ldInst); + AbstractLNAdapter abstractLNAdapter = AbstractLNAdapter.builder() + .withLDeviceAdapter(lDeviceAdapter) + .withLnClass(lnClass) + .withLnInst(lnInst) + .withLnPrefix(prefix) + .build(); + + // check for signal existence + abstractLNAdapter.isExtRefExist(signalInfo); + + // find potential binders for the signalInfo + return lDeviceAdapter.getParentAdapter().getParentAdapter().streamIEDAdapters() + .map(iedAdapter1 -> iedAdapter1.getExtRefBinders(signalInfo)) + .flatMap(Collection::stream) + .sorted() + .toList(); + } + + private LDeviceAdapter createLDeviceAdapter(SCL scd, String iedName, String ldInst) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); + return iedAdapter.getLDeviceAdapterByLdInst(ldInst); + } + + @Override + public List getExtRefSourceInfo(SCL scd, ExtRefInfo extRefInfo) throws ScdException { + + ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); + if (!signalInfo.isValid()) { + throw new ScdException("Invalid or missing attributes in ExtRef signal info"); + } + ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo(); + if (!bindingInfo.isValid()) { + throw new ScdException("Invalid or missing attributes in ExtRef binding info"); + } + + String iedName = extRefInfo.getHolderIEDName(); + if (bindingInfo.getIedName().equals(iedName)) { + throw new ScdException("Internal binding can't have control block"); + } + + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + + // Get CBs + IEDAdapter srcIEDAdapter = sclRootAdapter.getIEDAdapterByName(bindingInfo.getIedName()); + LDeviceAdapter srcLDeviceAdapter = srcIEDAdapter.findLDeviceAdapterByLdInst(extRefInfo.getBindingInfo().getLdInst()) + .orElseThrow(); + + List> aLNAdapters = srcLDeviceAdapter.getLNAdaptersIncludingLN0(); + + return aLNAdapters.stream() + .map(abstractLNAdapter1 -> abstractLNAdapter1.getControlBlocksForMatchingFCDA(extRefInfo)) + .flatMap(Collection::stream) + .toList(); + } + + @Override + public Set getDAI(SCL scd, String iedName, String ldInst, DataAttributeRef dataAttributeRef, boolean updatable) throws ScdException { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); + LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst); + return lDeviceAdapter.getDAI(dataAttributeRef, updatable); + } + + @Override + public Set getEnumTypeValues(SCL scd, String idEnum) throws ScdException { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + DataTypeTemplateAdapter dataTypeTemplateAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); + EnumTypeAdapter enumTypeAdapter = dataTypeTemplateAdapter.getEnumTypeAdapterById(idEnum) + .orElseThrow(() -> new ScdException("Unknown EnumType Id: " + idEnum)); + return enumTypeAdapter.getCurrentElem().getEnumVal().stream() + .map(tEnumVal -> new EnumValDTO(tEnumVal.getOrd(), tEnumVal.getValue())) + .collect(Collectors.toSet()); + } + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SubstationService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SubstationService.java similarity index 61% rename from sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SubstationService.java rename to sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SubstationService.java index 8e92407dd..1e51e398e 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SubstationService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/SubstationService.java @@ -2,51 +2,23 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl; +package org.lfenergy.compas.sct.commons; import lombok.NonNull; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TBay; import org.lfenergy.compas.scl2007b4.model.TSubstation; import org.lfenergy.compas.scl2007b4.model.TVoltageLevel; +import org.lfenergy.compas.sct.commons.api.SubstationEditor; import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter; -/** - * A representation of the {@link SubstationService SubstationService}. - *

    - * The following features are supported: - *

    - *
      - *
    • {@link SubstationService#addSubstation(SCL, SCL) Adds the Substation object from given SCL object}
    • - *
    • {@link SubstationService#updateVoltageLevel(SubstationAdapter, TVoltageLevel) Adds the TVoltageLevel element under TSubstation reference object}
    • - *
    • {@link SubstationService#updateBay(VoltageLevelAdapter, TBay) Adds the TBay element under TVoltageLevel reference object}
    • - *
    - * @see org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter - * @see org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter - * @see org.lfenergy.compas.sct.commons.scl.sstation.BayAdapter - * @see org.lfenergy.compas.sct.commons.scl.sstation.FunctionAdapter - * @see org.lfenergy.compas.sct.commons.scl.sstation.LNodeAdapter - * @see org.lfenergy.compas.sct.commons.scl.PrivateService - */ -public final class SubstationService { +public class SubstationService implements SubstationEditor { - /** - * Private Controller, should not be instanced - */ - private SubstationService() { - throw new UnsupportedOperationException("This service class cannot be instantiated"); - } - - /** - * Adds or Updates Substation section in SCL - * @param scd SCL file in which Substation should be added/updated - * @param ssd SCL file from which Substation should be copied - * @throws ScdException throws when SCD contents already another Substation, or with different name, or contents - * more than one Substation - */ - public static void addSubstation(@NonNull SCL scd, @NonNull SCL ssd) throws ScdException { + @Override + public void addSubstation(@NonNull SCL scd, @NonNull SCL ssd) throws ScdException { if (scd.getSubstation().size() > 1) { throw new ScdException(String.format("SCD file must have 0 or 1 Substation, but got %d", scd.getSubstation().size())); } @@ -75,7 +47,7 @@ public static void addSubstation(@NonNull SCL scd, @NonNull SCL ssd) throws ScdE * @param vl VoltageLevel to create/update * @throws ScdException throws when unable to create new VoltageLevel section which is not already present in Substation */ - private static void updateVoltageLevel(@NonNull SubstationAdapter scdSubstationAdapter, TVoltageLevel vl) throws ScdException { + private void updateVoltageLevel(@NonNull SubstationAdapter scdSubstationAdapter, TVoltageLevel vl) throws ScdException { if (scdSubstationAdapter.getVoltageLevelAdapter(vl.getName()).isPresent()) { VoltageLevelAdapter scdVoltageLevelAdapter = scdSubstationAdapter.getVoltageLevelAdapter(vl.getName()) .orElseThrow(() -> new ScdException("Unable to create VoltageLevelAdapter")); @@ -92,7 +64,7 @@ private static void updateVoltageLevel(@NonNull SubstationAdapter scdSubstationA * @param scdVoltageLevelAdapter VoltageLevel in which Bay should be created/updated * @param tBay Bay to add */ - private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapter, TBay tBay) { + private void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapter, TBay tBay) { if (scdVoltageLevelAdapter.getBayAdapter(tBay.getName()).isPresent()) { scdVoltageLevelAdapter.getCurrentElem().getBay() .removeIf(t -> t.getName().equalsIgnoreCase(tBay.getName())); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ExtRefEditor.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ExtRefEditor.java new file mode 100644 index 000000000..f2df603fd --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/ExtRefEditor.java @@ -0,0 +1,115 @@ +// SPDX-FileCopyrightText: 2023 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.api; + +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.scl2007b4.model.TExtRef; +import org.lfenergy.compas.sct.commons.dto.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.util.ILDEPFSettings; +import org.lfenergy.compas.sct.commons.util.Utils; + +import java.util.List; + +/** + * Service class that will be used to create, update or delete elements related to the {@link TExtRef TExtRef} object. + *

    The following features are supported:

    + *
      + *
    • ExtRef features
    • + *
        + *
      1. {@link ExtRefEditor#updateExtRefBinders Update the TExtRef reference object for given ExtRefBindingInfo model}
      2. + *
      3. {@link ExtRefEditor#updateExtRefSource Update the TExtRef reference object for given ExtRefSourceInfo model}
      4. + *
      5. {@link ExtRefEditor#updateAllExtRefIedNames Update the iedName attribute in all TExtRef}
      6. + *
      7. {@link ExtRefEditor#createDataSetAndControlBlocks(SCL) Create DataSet and ControlBlock based on the TExtRef}
      8. + *
      9. {@link ExtRefEditor#createDataSetAndControlBlocks(SCL, String) Create DataSet and ControlBlock based on the TExtRef in given IED}
      10. + *
      11. {@link ExtRefEditor#createDataSetAndControlBlocks(SCL, String, String) Create DataSet and ControlBlock based on the TExtRef in given IED and LDevice}
      12. + *
      13. {@link ExtRefEditor#configureNetworkForAllControlBlocks Configure the network for the ControlBlocks}
      14. + *
      15. {@link ExtRefEditor#manageBindingForLDEPF Manage TExtRef Binding For LDevice (inst=LDEPF) within LDEPF configuration}
      16. + *
      + *
    + */ +public interface ExtRefEditor { + + /** + * Updates ExtRef binding data related to given ExtRef (extRefInfo) in given SCL file + * + * @param scd SCL file in which ExtRef to update should be found + * @param extRefInfo ExtRef signal for which we should find possible binders in SCL file + * @throws ScdException throws when mandatory data of ExtRef are missing + */ + void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws ScdException; + + /** + * Updates ExtRef source binding data's based on given data in extRefInfo + * + * @param scd SCL file in which ExtRef source data's to update should be found + * @param extRefInfo new data for ExtRef source binding data + * @return TExtRef object as update ExtRef with new source binding data + * @throws ScdException throws when mandatory data of ExtRef are missing + */ + TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws ScdException; + + /** + * Updates iedName attribute of all ExtRefs in the Scd. + * + * @return list of encountered errors + */ + List updateAllExtRefIedNames(SCL scd); + + /** + * Create All DataSet and ControlBlock in the SCL based on the ExtRef + * + * @param scd input SCD object. It could be modified by adding new DataSet and ControlBlocks + * @return list of encountered errors + */ + List createDataSetAndControlBlocks(SCL scd); + + /** + * Create All DataSet and ControlBlock for the ExtRef in given IED + * + * @param scd input SCD object. The object will be modified with the new DataSet and ControlBlocks + * @param targetIedName the name of the IED where the ExtRef are + * @return list of encountered errors + */ + List createDataSetAndControlBlocks(SCL scd, String targetIedName); + + /** + * Create All DataSet and ControlBlock for the ExtRef in given IED and LDevice + * + * @param scd input SCD object. The object will be modified with the new DataSet and ControlBlocks + * @param targetIedName the name of the IED where the ExtRef are + * @param targetLDeviceInst the name of the LDevice where the ExtRef are + * @return list of encountered errors + */ + List createDataSetAndControlBlocks(SCL scd, String targetIedName, String targetLDeviceInst); + + /** + * Configure the network for all the ControlBlocks. + * Create (or update if already existing) these elements + * - 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") + * @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); + + /** + * ExtRef Binding For LDevice (inst=LDEPF) that matching LDEPF configuration + * @param scd SCL + * @param settings ILDEPFSettings + * @return list of encountered errors + */ + List manageBindingForLDEPF(SCL scd, ILDEPFSettings settings); + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/HmiEditor.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/HmiEditor.java new file mode 100644 index 000000000..548cac764 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/HmiEditor.java @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2023 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.api; + +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.scl2007b4.model.TFCDA; +import org.lfenergy.compas.scl2007b4.model.TReportControl; + +import java.util.List; + +/** + * Service class that will be used to manage elements related to the HMI {@link TReportControl Report Control Blocks}. + * + * @see Issue !258 + */ +public interface HmiEditor { + + /** + * Create the DataSet and ReportControl Blocks for the HMI with the given FCDAs. + * + * @param fcdas List of FCDA for which we must create the DataSet and ReportControl Blocks + */ + void createAllHmiReportControlBlocks(SCL scd, List fcdas); +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SclEditor.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SclEditor.java new file mode 100644 index 000000000..d98582303 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SclEditor.java @@ -0,0 +1,172 @@ +// SPDX-FileCopyrightText: 2023 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.api; + +import lombok.NonNull; +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.scl2007b4.model.TLNode; +import org.lfenergy.compas.sct.commons.dto.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; + +import java.util.List; +import java.util.UUID; + +/** + * Service class that will be used to create, update or delete elements in {@link SCL SCL} XML Files. + *

    The following features are supported:

    + *
      + *
    • Initialization functions
    • + *
        + *
      1. {@link SclEditor#initScl Initialize the SCL object}
      2. + *
      3. {@link SclEditor#addHistoryItem Adds History object under THeader reference object}
      4. + *
      5. {@link SclEditor#updateHeader Update Header reference object}
      6. + *
      + *
    • IED features
    • + *
        + *
      1. {@link SclEditor#addIED Adds the IED object}
      2. + *
      + *
    • Communication features
    • + *
        + *
      1. {@link SclEditor#addSubnetworks Adds the Subnetwork elements under TCommunication reference object}
      2. + *
      + *
    • DAI features
    • + *
        + *
      1. {@link SclEditor#updateDAI Update the TDAI reference object for given iedName, ldInst and DataAttributeRef model}
      2. + *
      + *
    + * @see ExtRefEditor + * @see SubstationEditor + * @see HmiEditor + */ +public interface SclEditor { + + /** + * Initialise SCD file with Header and Private SCLFileType + * + * @param hId SCL Header ID + * @param hVersion SCL Header Version + * @param hRevision SCL Header Revision + * @return SCL SCD object + * @throws ScdException throws when inconsistance in SCL file + */ + SCL initScl(final UUID hId, final String hVersion, final String hRevision) throws ScdException; + /** + * Adds new HistoryItem in SCL file + * + * @param scd SCL file in which new History should be added + * @param who Who realize the action + * @param what What kind of action is realized + * @param why Why this action is done + */ + void addHistoryItem(SCL scd, String who, String what, String why); + + /** + * Updates Header of SCL file + * + * @param scd SCL file in which Header should be updated + * @param headerDTO Header new values + */ + void updateHeader(@NonNull SCL scd, @NonNull HeaderDTO headerDTO); + + /** + * Adds IED in SCL file (Related DataTypeTemplate of SCL is updated also) + * + * @param scd SCL file in which IED should be added + * @param iedName name of IED to add in SCL + * @param icd ICD containing IED to add and related DataTypeTemplate + * @throws ScdException throws when inconsistency between IED to add and SCL file content + */ + void addIED(SCL scd, String iedName, SCL icd) throws ScdException; + + /** + * Adds new SubNetworks in SCL file from ICD file + * + * @param scd SCL file in which SubNetworks should be added + * @param subNetworks List of SubNetworks DTO contenting SubNetwork and ConnectedAp parameter names + * @param icd ICD file from which SubNetworks functional data are copied from + * @throws ScdException throws when no Communication in SCL and createIfNotExists == false + */ + void addSubnetworks(SCL scd, List subNetworks, SCL icd) throws ScdException; + + /** + * Updates DAI based on given data in dataAttributeRef + * + * @param scd SCL file in which DataTypeTemplate of DAI should be found + * @param iedName name of IED in which DAI is localized + * @param ldInst ldInst of LDevice in which DAI is localized + * @param dataAttributeRef reference summarized DataTypeTemplate related to DAI to update + * @throws ScdException when inconsistency are found in th SCL's + * DataTypeTemplate. Which should normally not happens. + */ + void updateDAI(SCL scd, String iedName, String ldInst, DataAttributeRef dataAttributeRef) throws ScdException; + + /** + * Imports IEDs, DataTypeTemplates and Communication nodes of STD files into SCL (SCD) file + * STD : System Template Definition + * To import STD into SCD, this step are realized + *
      + *
    • Check SCD and STD compatibilities by checking if there is at least one ICD_SYSTEM_VERSION_UUID in + * LNode/Private CompasICDHeader of SCL/Substation/.. not present in IED/Private CompasICDHeader of STD
    • + *
    • List all LNode/Private COMPAS-ICDHeader of SCL/Substation/.. and remove duplicated one with same iedName in order to + * ovoid repetition in actions
    • + *
    • For each Private.ICDSystemVersionUUID and Private.iedName in Substation/ of SCL find corresponding STD File
    • + *
    • import /IED /DataTypeTemplate from that STD file and update IEDName of /IED in SCD file
    • + *
    • import connectedAP and rename ConnectedAP/@iedName in Communication node in SCD file
    • + *
    + * + * @param scd SCL object in which content of STD files are imported + * @param stds list of STD files contenting datas to import into SCD + * @param subNetworkTypes couple of Subnetwork name and possible corresponding ConnectedAP names + * @throws ScdException throws when inconsistency between Substation of SCL content and gien STD files as : + *
      + *
    • ICD_SYSTEM_VERSION_UUID in IED/Private of STD is not present in COMPAS-ICDHeader in Substation/../LNode of SCL
    • + *
    • There are several STD files corresponding to ICD_SYSTEM_VERSION_UUID of COMPAS-ICDHeader in Substation/../LNode of SCL
    • + *
    • There is no STD file found corresponding to COMPAS-ICDHeader in Substation/../LNode of SCL
    • + *
    • COMPAS-ICDHeader is not the same in Substation/../LNode of SCL and in IED/Private of STD
    • + *
    • COMPAS_ICDHEADER in Substation/../LNode of SCL not found in IED/Private of STD
    • + *
    + */ + void importSTDElementsInSCD(SCL scd, List stds, List subNetworkTypes) throws ScdException; + + /** + * Removes all ControlBlocks and DataSets for all LNs in SCL + * + * @param scl SCL file for which ControlBlocks and DataSets should be deleted + */ + void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final SCL scl); + + /** + * Activate used LDevice and Deactivate unused LDevice in {@link TLNode TLNode } + * + * @param scd SCL file for which LDevice should be activated or deactivated + * @return list of encountered errors + */ + List updateLDeviceStatus(SCL scd); + + /** + * Checks Control Blocks, DataSets and FCDA number limitation into Access Points + * + * @param scd SCL file for which LDevice should be activated or deactivated + * @return list of encountered errors + */ + List analyzeDataGroups(SCL scd); + + /** + * Update DAIs of DO InRef in all LN0 of the SCD using matching ExtRef information. + * + * @param scd SCL file for which DOs InRef should be updated with matching ExtRef information + * @return list of encountered errors + */ + List updateDoInRef(SCL scd); + + /** + * Update and/or create Monitoring LNs (LSVS and LGOS) for bound GOOSE and SMV Control Blocks + * + * @param scd SCL file for which LNs (LSVS and LGOS) should be updated and/or created in each LDevice LDSUIED with matching ExtRef information + * @return list of encountered errors + */ + List manageMonitoringLns(SCL scd); + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SclElementsProvider.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SclElementsProvider.java new file mode 100644 index 000000000..2c69a6fbc --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SclElementsProvider.java @@ -0,0 +1,109 @@ +// SPDX-FileCopyrightText: 2023 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.api; + +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.sct.commons.dto.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; + +import java.util.List; +import java.util.Set; + +/** + * Service class that will be used to retrieve {@link SCL SCL} XML Files. + * The ElementsProvider class needs to be able to find/list entries. + *

    The following features are supported:

    + *
      + *
    • Communication features
    • + *
        + *
      1. {@link SclElementsProvider#getSubnetwork(SCL) Returns list of SubNetworkDTO }
      2. + *
      + *
    • ExtRef features
    • + *
        + *
      1. {@link SclElementsProvider#getExtRefInfo Returns list of ExtRefInfo }
      2. + *
      3. {@link SclElementsProvider#getExtRefBinders Returns list of ExtRefBindingInfo }
      4. + *
      5. {@link SclElementsProvider#getExtRefSourceInfo Returns list of ExtRefSourceInfo }
      6. + *
      + *
    • DAI features
    • + *
        + *
      1. {@link SclElementsProvider#getDAI Returns list of DataAttributeRef }
      2. + *
      + *
    • EnumType features
    • + *
        + *
      1. {@link SclElementsProvider#getEnumTypeValues(SCL, String) Returns Map (ord, enumVal) of TEnumType reference object}
      2. + *
      + *
    + */ +public interface SclElementsProvider { + /** + * Gets list of SCL SubNetworks + * + * @param scd SCL file in which SubNetworks should be found + * @return List of SubNetworkDTO from SCL + * @throws ScdException throws when no Communication in SCL and createIfNotExists == false + */ + List getSubnetwork(SCL scd) throws ScdException; + + /** + * Gets all ExtRef from specific IED/LDevice in SCL file + * + * @param scd SCL file in which ExtRefs should be found + * @param iedName name of IED in which LDevice is localized + * @param ldInst LdInst of LDevice in which all ExtRefs should be found + * @return list of ExtRefInfo from specified parameter SCL/IED/LDevice + * @throws ScdException throws when unknown specified IED or LDevice + */ + List getExtRefInfo(SCL scd, String iedName, String ldInst) throws ScdException; + + /** + * Gets all possible ExtRefs to bind in SCL file with given ExtRef (signalInfo) in SCL file + * + * @param scd SCL file in which ExtRefs should be found + * @param iedName name of IED in which LDevice is localized + * @param ldInst ldInst of LDevice in which LN is localized + * @param lnClass lnClass of LN in which ExtRef signal to find binders is localized + * @param lnInst lnInst of LN in which ExtRef signal to find binders is localized + * @param prefix prefix of LN in which ExtRef signal to find binders is localized + * @param signalInfo ExtRef signal for which we should find possible binders in SCL file binders + * @return list of ExtRefBindingInfo object (containing binding data for each LNode in current SCL file) sorted by {@link ExtRefBindingInfo#compareTo(ExtRefBindingInfo) compareTo} method. + * @throws ScdException throws when ExtRef contains inconsistency data + */ + List getExtRefBinders(SCL scd, String iedName, String ldInst, String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException; + + /** + * Gets all Control Blocks related to extRefInfo in given SCL file + * + * @param scd SCL file in which ControlBlocks should be found + * @param extRefInfo ExtRef signal for which we should find related ControlBlocks + * @return list of ControlBlock object as ControlBlocks of LNode specified in extRefInfo + * @throws ScdException throws when mandatory data of ExtRef are missing + */ + List getExtRefSourceInfo(SCL scd, ExtRefInfo extRefInfo) throws ScdException; + + /** + * Gets a list of summarized DataTypeTemplate for DataAttribute DA (updatable or not) related to the one given + * in dataAttributeRef + * + * @param scd SCL file in which DataTypeTemplate of DAIs should be found + * @param iedName name of IED in which DAs are localized + * @param ldInst ldInst of LDevice in which DAIs are localized + * @param dataAttributeRef reference summarized DataTypeTemplate related to IED DAIs + * @param updatable true to retrieve DataTypeTemplate's related to only updatable DAIs, false to retrieve all + * @return Set of Data Attribute Reference for DataAttribute (updatable or not) + * @throws ScdException SCD illegal arguments exception, missing mandatory data + */ + Set getDAI(SCL scd, String iedName, String ldInst, DataAttributeRef dataAttributeRef, boolean updatable) throws ScdException; + + /** + * Gets EnumTypes values of ID idEnum from DataTypeTemplate of SCL file + * + * @param scd SCL file in which EnumType should be found + * @param idEnum ID of EnumType for which values are retrieved + * @return list of couple EnumType value and it's order + * @throws ScdException throws when unknown EnumType + */ + Set getEnumTypeValues(SCL scd, String idEnum) throws ScdException; + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SubstationEditor.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SubstationEditor.java new file mode 100644 index 000000000..1c8260e15 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/SubstationEditor.java @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: 2023 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.api; + +import lombok.NonNull; +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.scl2007b4.model.TSubstation; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; + +/** + * Service class that will be used to create, update or delete elements related to the {@link TSubstation TSubstation} object. + *

    The following features are supported:

    + *
      + *
    • {@link SubstationEditor#addSubstation(SCL, SCL) Adds the Substation object from given SCL object}
    • + *
    + * @see SubstationAdapter + */ +public interface SubstationEditor { + + /** + * Adds or Updates Substation section in SCL + * @param scd SCL file in which Substation should be added/updated + * @param ssd SCL file from which Substation should be copied + * @throws ScdException throws when SCD contents already another Substation, or with different name, or contents + * more than one Substation + */ + void addSubstation(@NonNull SCL scd, @NonNull SCL ssd) throws ScdException; + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/package-info.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/package-info.java new file mode 100644 index 000000000..7d54345d1 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/package-info.java @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: 2023 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +/** + *

    commons.api contains interfaces for manipulating SCL Files

    + */ +package org.lfenergy.compas.sct.commons.api; \ No newline at end of file diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/PrivateLinkedToStds.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/PrivateLinkedToStds.java new file mode 100644 index 000000000..962811c21 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/PrivateLinkedToStds.java @@ -0,0 +1,14 @@ +// SPDX-FileCopyrightText: 2023 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.dto; + +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.scl2007b4.model.TPrivate; + +import java.util.List; + +public record PrivateLinkedToStds(TPrivate tPrivate, List stdList) { + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclService.java deleted file mode 100644 index 273adc80d..000000000 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclService.java +++ /dev/null @@ -1,606 +0,0 @@ -// SPDX-FileCopyrightText: 2021 RTE FRANCE -// -// SPDX-License-Identifier: Apache-2.0 - -package org.lfenergy.compas.sct.commons.scl; - -import lombok.NonNull; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.tuple.Pair; -import org.lfenergy.compas.scl2007b4.model.*; -import org.lfenergy.compas.sct.commons.dto.*; -import org.lfenergy.compas.sct.commons.exception.ScdException; -import org.lfenergy.compas.sct.commons.scl.com.CommunicationAdapter; -import org.lfenergy.compas.sct.commons.scl.com.ConnectedAPAdapter; -import org.lfenergy.compas.sct.commons.scl.com.SubNetworkAdapter; -import org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter; -import org.lfenergy.compas.sct.commons.scl.dtt.EnumTypeAdapter; -import org.lfenergy.compas.sct.commons.scl.dtt.LNodeTypeAdapter; -import org.lfenergy.compas.sct.commons.scl.header.HeaderAdapter; -import org.lfenergy.compas.sct.commons.scl.icd.IcdHeader; -import org.lfenergy.compas.sct.commons.scl.ied.*; -import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; -import org.lfenergy.compas.sct.commons.util.Utils; - -import java.util.*; -import java.util.stream.Collectors; - -import static org.lfenergy.compas.sct.commons.util.CommonConstants.IED_TEST_NAME; -import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_ICDHEADER; - -/** - * A representation of the {@link SclService SclService}. - *

    - * The following features are supported: - *

    - *
      - *
    • Initialization functions
    • - *
        - *
      1. {@link SclService#initScl(UUID, String, String) Initialize the SCL object}
      2. - *
      3. {@link SclService#addHistoryItem(SCL, String, String, String) Adds History object under THeader reference object}
      4. - *
      5. {@link SclService#updateHeader(SCL, HeaderDTO) Update Header reference object}
      6. - *
      - *
    • IED features
    • - *
        - *
      1. {@link SclService#addIED(SCL, String, SCL) Adds the IED object}
      2. - *
      - *
    • Communication features
    • - *
        - *
      1. {@link SclService#getSubnetwork(SCL) Returns list of SubNetworkDTO }
      2. - *
      3. {@link SclService#addSubnetworks(SCL, List, SCL) Adds the Subnetwork elements under TCommunication reference object}
      4. - *
      - *
    • ExtRef features
    • - *
        - *
      1. {@link SclService#getExtRefInfo Returns list of ExtRefInfo }
      2. - *
      3. {@link SclService#getExtRefBinders Returns list of ExtRefBindingInfo }
      4. - *
      5. {@link SclService#updateExtRefBinders(SCL, ExtRefInfo) Update the TExtRef reference object for given ExtRefBindingInfo model}
      6. - *
      7. {@link SclService#getExtRefSourceInfo Returns list of ExtRefSourceInfo }
      8. - *
      9. {@link SclService#updateExtRefSource(SCL, ExtRefInfo) Update the TExtRef reference object for given ExtRefSourceInfo model}
      10. - *
      - *
    • DAI features
    • - *
        - *
      1. {@link SclService#getDAI Returns list of DataAttributeRef }
      2. - *
      3. {@link SclService#updateDAI(SCL, String, String, DataAttributeRef) - * Update the TDAI reference object for given iedName, ldInst and DataAttributeRef model}
      4. - *
      - *
    • EnumType features
    • - *
        - *
      1. {@link SclService#getEnumTypeValues(SCL, String) Returns Map (ord, enumVal) of TEnumType reference object}
      2. - *
      - * - *
    - * - * @see org.lfenergy.compas.sct.commons.scl.header.HeaderAdapter - * @see org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter - * @see org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter - * @see org.lfenergy.compas.sct.commons.scl.com.CommunicationAdapter - * @see org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter - */ -@Slf4j -public class SclService { - - private static final String UNKNOWN_LDEVICE_S_IN_IED_S = "Unknown LDevice (%s) in IED (%s)"; - private static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info"; - - private SclService() { - throw new IllegalStateException("SclService class"); - } - - /** - * Initialise SCD file with Header and Private SCLFileType - * - * @param hId SCL Header ID - * @param hVersion SCL Header Version - * @param hRevision SCL Header Revision - * @return SCL SCD object - * @throws ScdException throws when inconsistance in SCL file - */ - public static SCL initScl(final UUID hId, final String hVersion, final String hRevision) throws ScdException { - SclRootAdapter scdAdapter = new SclRootAdapter(hId.toString(), hVersion, hRevision); - scdAdapter.addPrivate(PrivateService.createPrivate(TCompasSclFileType.SCD)); - return scdAdapter.getCurrentElem(); - } - - /** - * Adds new HistoryItem in SCL file - * - * @param scd SCL file in which new History should be added - * @param who Who realize the action - * @param what What kind of action is realized - * @param why Why this action is done - */ - public static void addHistoryItem(SCL scd, String who, String what, String why) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - HeaderAdapter headerAdapter = sclRootAdapter.getHeaderAdapter(); - headerAdapter.addHistoryItem(who, what, why); - } - - /** - * Updates Header of SCL file - * - * @param scd SCL file in which Header should be updated - * @param headerDTO Header new values - */ - public static void updateHeader(@NonNull SCL scd, @NonNull HeaderDTO headerDTO) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - HeaderAdapter headerAdapter = sclRootAdapter.getHeaderAdapter(); - boolean hUpdated = false; - String hVersion = headerDTO.getVersion(); - String hRevision = headerDTO.getRevision(); - if (hVersion != null && !hVersion.equals(headerAdapter.getHeaderVersion())) { - headerAdapter.updateVersion(hVersion); - hUpdated = true; - } - if (hRevision != null && !hRevision.equals(headerAdapter.getHeaderRevision())) { - headerAdapter.updateRevision(hRevision); - hUpdated = true; - } - if (hUpdated && !headerDTO.getHistoryItems().isEmpty()) { - headerAdapter.addHistoryItem( - headerDTO.getHistoryItems().get(0).getWho(), - headerDTO.getHistoryItems().get(0).getWhat(), - headerDTO.getHistoryItems().get(0).getWhy() - ); - } - } - - /** - * Adds IED in SCL file (Related DataTypeTemplate of SCL is updated also) - * - * @param scd SCL file in which IED should be added - * @param iedName name of IED to add in SCL - * @param icd ICD containing IED to add and related DataTypeTemplate - * @throws ScdException throws when inconsistency between IED to add and SCL file content - */ - public static void addIED(SCL scd, String iedName, SCL icd) throws ScdException { - new SclRootAdapter(scd).addIED(icd, iedName); - } - - /** - * Adds new SubNetworks in SCL file from ICD file - * - * @param scd SCL file in which SubNetworks should be added - * @param subNetworks List of SubNetworks DTO contenting SubNetwork and ConnectedAp parameter names - * @param icd ICD file from which SubNetworks functional data are copied from - * @throws ScdException throws when no Communication in SCL and createIfNotExists == false - */ - public static void addSubnetworks(SCL scd, List subNetworks, SCL icd) throws ScdException { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - CommunicationAdapter communicationAdapter; - if (!subNetworks.isEmpty()) { - communicationAdapter = sclRootAdapter.getCommunicationAdapter(true); - for (SubNetworkDTO subNetworkDTO : subNetworks) { - String snName = subNetworkDTO.getName(); - String snType = subNetworkDTO.getType(); - for (ConnectedApDTO accessPoint : subNetworkDTO.getConnectedAPs()) { - String iedName = accessPoint.iedName(); - String apName = accessPoint.apName(); - communicationAdapter.addSubnetwork(snName, snType, iedName, apName); - - Optional subNetworkAdapter = communicationAdapter.getSubnetworkByName(snName); - if (subNetworkAdapter.isPresent()) { - ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.get().getConnectedAPAdapter(iedName, apName); - connectedAPAdapter.copyAddressAndPhysConnFromIcd(icd); - } - } - } - } - } - - /** - * Gets list of SCL SubNetworks - * - * @param scd SCL file in which SubNetworks should be found - * @return List of SubNetworkDTO from SCL - * @throws ScdException throws when no Communication in SCL and createIfNotExists == false - */ - public static List getSubnetwork(SCL scd) throws ScdException { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - CommunicationAdapter communicationAdapter = sclRootAdapter.getCommunicationAdapter(false); - return communicationAdapter.getSubNetworkAdapters().stream() - .map(SubNetworkDTO::from) - .toList(); - } - - /** - * Gets all ExtRef from specific IED/LDevice in SCL file - * - * @param scd SCL file in which ExtRefs should be found - * @param iedName name of IED in which LDevice is localized - * @param ldInst LdInst of LDevice in which all ExtRefs should be found - * @return list of ExtRefInfo from specified parameter SCL/IED/LDevice - * @throws ScdException throws when unknown specified IED or LDevice - */ - public static List getExtRefInfo(SCL scd, String iedName, String ldInst) throws ScdException { - LDeviceAdapter lDeviceAdapter = createLDeviceAdapter(scd, iedName, ldInst); - return lDeviceAdapter.getExtRefInfo(); - } - - /** - * Create LDevice - * - * @param scd SCL file in which LDevice should be found - * @param iedName name of IED in which LDevice is localized - * @param ldInst LdInst of LDevice for which adapter is created - * @return created LDevice adapter - */ - private static LDeviceAdapter createLDeviceAdapter(SCL scd, String iedName, String ldInst) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); - return iedAdapter.findLDeviceAdapterByLdInst(ldInst) - .orElseThrow(() -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName))); - } - - /** - * Gets all possible ExtRefs to bind in SCL file with given ExtRef (signalInfo) in SCL file - * - * @param scd SCL file in which ExtRefs should be found - * @param iedName name of IED in which LDevice is localized - * @param ldInst ldInst of LDevice in which LN is localized - * @param lnClass lnClass of LN in which ExtRef signal to find binders is localized - * @param lnInst lnInst of LN in which ExtRef signal to find binders is localized - * @param prefix prefix of LN in which ExtRef signal to find binders is localized - * @param signalInfo ExtRef signal for which we should find possible binders in SCL file binders - * @return list of ExtRefBindingInfo object (containing binding data for each LNode in current SCL file) sorted by {@link ExtRefBindingInfo#compareTo(ExtRefBindingInfo) compareTo} method. - * @throws ScdException throws when ExtRef contains inconsistency data - */ - public static List getExtRefBinders(SCL scd, String iedName, String ldInst, String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException { - LDeviceAdapter lDeviceAdapter = createLDeviceAdapter(scd, iedName, ldInst); - AbstractLNAdapter abstractLNAdapter = AbstractLNAdapter.builder() - .withLDeviceAdapter(lDeviceAdapter) - .withLnClass(lnClass) - .withLnInst(lnInst) - .withLnPrefix(prefix) - .build(); - - // check for signal existence - abstractLNAdapter.isExtRefExist(signalInfo); - - // find potential binders for the signalInfo - return lDeviceAdapter.getParentAdapter().getParentAdapter().streamIEDAdapters() - .map(iedAdapter1 -> iedAdapter1.getExtRefBinders(signalInfo)) - .flatMap(Collection::stream) - .sorted() - .toList(); - } - - /** - * Updates ExtRef binding data related to given ExtRef (extRefInfo) in given SCL file - * - * @param scd SCL file in which ExtRef to update should be found - * @param extRefInfo ExtRef signal for which we should find possible binders in SCL file - * @throws ScdException throws when mandatory data of ExtRef are missing - */ - public static void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws ScdException { - if (extRefInfo.getBindingInfo() == null || extRefInfo.getSignalInfo() == null) { - throw new ScdException("ExtRef Signal and/or Binding information are missing"); - } - String iedName = extRefInfo.getHolderIEDName(); - String ldInst = extRefInfo.getHolderLDInst(); - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); - LDeviceAdapter lDeviceAdapter = iedAdapter.findLDeviceAdapterByLdInst(ldInst) - .orElseThrow(() -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName))); - - AbstractLNAdapter abstractLNAdapter = AbstractLNAdapter.builder() - .withLDeviceAdapter(lDeviceAdapter) - .withLnClass(extRefInfo.getHolderLnClass()) - .withLnInst(extRefInfo.getHolderLnInst()) - .withLnPrefix(extRefInfo.getHolderLnPrefix()) - .build(); - - abstractLNAdapter.updateExtRefBinders(extRefInfo); - } - - /** - * Gets all Control Blocks related to extRefInfo in given SCL file - * - * @param scd SCL file in which ControlBlocks should be found - * @param extRefInfo ExtRef signal for which we should find related ControlBlocks - * @return list of ControlBlock object as ControlBlocks of LNode specified in extRefInfo - * @throws ScdException throws when mandatory data of ExtRef are missing - */ - public static List getExtRefSourceInfo(SCL scd, ExtRefInfo extRefInfo) throws ScdException { - - ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); - if (!signalInfo.isValid()) { - throw new ScdException("Invalid or missing attributes in ExtRef signal info"); - } - ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo(); - if (!bindingInfo.isValid()) { - throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); - } - - String iedName = extRefInfo.getHolderIEDName(); - if (bindingInfo.getIedName().equals(iedName)) { - throw new ScdException("Internal binding can't have control block"); - } - - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - - // Get CBs - IEDAdapter srcIEDAdapter = sclRootAdapter.getIEDAdapterByName(bindingInfo.getIedName()); - LDeviceAdapter srcLDeviceAdapter = srcIEDAdapter.findLDeviceAdapterByLdInst(extRefInfo.getBindingInfo().getLdInst()) - .orElseThrow(); - - List> aLNAdapters = srcLDeviceAdapter.getLNAdaptersIncludingLN0(); - - return aLNAdapters.stream() - .map(abstractLNAdapter1 -> abstractLNAdapter1.getControlBlocksForMatchingFCDA(extRefInfo)) - .flatMap(Collection::stream) - .toList(); - - } - - /** - * Updates ExtRef source binding data's based on given data in extRefInfo - * - * @param scd SCL file in which ExtRef source data's to update should be found - * @param extRefInfo new data for ExtRef source binding data - * @return TExtRef object as update ExtRef with new source binding data - * @throws ScdException throws when mandatory data of ExtRef are missing - */ - public static TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws ScdException { - String iedName = extRefInfo.getHolderIEDName(); - String ldInst = extRefInfo.getHolderLDInst(); - String lnClass = extRefInfo.getHolderLnClass(); - String lnInst = extRefInfo.getHolderLnInst(); - String prefix = extRefInfo.getHolderLnPrefix(); - - ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); - if (signalInfo == null || !signalInfo.isValid()) { - throw new ScdException("Invalid or missing attributes in ExtRef signal info"); - } - ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo(); - if (bindingInfo == null || !bindingInfo.isValid()) { - throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); - } - if (bindingInfo.getIedName().equals(iedName) || TServiceType.POLL.equals(bindingInfo.getServiceType())) { - throw new ScdException("Internal binding can't have control block"); - } - ExtRefSourceInfo sourceInfo = extRefInfo.getSourceInfo(); - if (sourceInfo == null || !sourceInfo.isValid()) { - throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); - } - - LDeviceAdapter lDeviceAdapter = createLDeviceAdapter(scd, iedName, ldInst); - AbstractLNAdapter anLNAdapter = AbstractLNAdapter.builder() - .withLDeviceAdapter(lDeviceAdapter) - .withLnClass(lnClass) - .withLnInst(lnInst) - .withLnPrefix(prefix) - .build(); - return anLNAdapter.updateExtRefSource(extRefInfo); - } - - /** - * Gets a list of summarized DataTypeTemplate for DataAttribute DA (updatable or not) related to the one given - * in dataAttributeRef - * - * @param scd SCL file in which DataTypeTemplate of DAIs should be found - * @param iedName name of IED in which DAs are localized - * @param ldInst ldInst of LDevice in which DAIs are localized - * @param dataAttributeRef reference summarized DataTypeTemplate related to IED DAIs - * @param updatable true to retrieve DataTypeTemplate's related to only updatable DAIs, false to retrieve all - * @return Set of Data Attribute Reference for DataAttribute (updatable or not) - * @throws ScdException SCD illegal arguments exception, missing mandatory data - */ - public static Set getDAI(SCL scd, String iedName, String ldInst, DataAttributeRef dataAttributeRef, boolean updatable) throws ScdException { - LDeviceAdapter lDeviceAdapter = createLDeviceAdapter(scd, iedName, ldInst); - return lDeviceAdapter.getDAI(dataAttributeRef, updatable); - } - - /** - * Updates DAI based on given data in dataAttributeRef - * - * @param scd SCL file in which DataTypeTemplate of DAI should be found - * @param iedName name of IED in which DAI is localized - * @param ldInst ldInst of LDevice in which DAI is localized - * @param dataAttributeRef reference summarized DataTypeTemplate related to DAI to update - * @throws ScdException when inconsistency are found in th SCL's - * DataTypeTemplate. Which should normally not happens. - */ - public static void updateDAI(SCL scd, String iedName, String ldInst, DataAttributeRef dataAttributeRef) throws ScdException { - long startTime = System.nanoTime(); - log.info(Utils.entering()); - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - DataTypeTemplateAdapter dttAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); - LNodeTypeAdapter lNodeTypeAdapter = dttAdapter.getLNodeTypeAdapterById(dataAttributeRef.getLnType()) - .orElseThrow(() -> new ScdException("Unknown LNodeType : " + dataAttributeRef.getLnType())); - lNodeTypeAdapter.check(dataAttributeRef.getDoName(), dataAttributeRef.getDaName()); - - if (TPredefinedBasicTypeEnum.OBJ_REF == dataAttributeRef.getBType()) { - Long sGroup = dataAttributeRef.getDaName().getDaiValues().keySet().stream().findFirst().orElse(-1L); - String val = sGroup < 0 ? null : dataAttributeRef.getDaName().getDaiValues().get(sGroup); - sclRootAdapter.checkObjRef(val); - } - - IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); - LDeviceAdapter lDeviceAdapter = iedAdapter.findLDeviceAdapterByLdInst(ldInst) - .orElseThrow(() -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName))); - - AbstractLNAdapter lnAdapter = AbstractLNAdapter.builder() - .withLDeviceAdapter(lDeviceAdapter) - .withLnClass(dataAttributeRef.getLnClass()) - .withLnInst(dataAttributeRef.getLnInst()) - .withLnPrefix(dataAttributeRef.getPrefix()) - .build(); - - if (TPredefinedCDCEnum.ING == dataAttributeRef.getCdc() || TPredefinedCDCEnum.ASG == dataAttributeRef.getCdc()) { - DAITracker daiTracker = new DAITracker(lnAdapter, dataAttributeRef.getDoName(), dataAttributeRef.getDaName()); - daiTracker.validateBoundedDAI(); - } - lnAdapter.updateDAI(dataAttributeRef); - log.info(Utils.leaving(startTime)); - } - - /** - * Gets EnumTypes values of ID idEnum from DataTypeTemplate of SCL file - * - * @param scd SCL file in which EnumType should be found - * @param idEnum ID of EnumType for which values are retrieved - * @return list of couple EnumType value and it's order - * @throws ScdException throws when unknown EnumType - */ - public static Set getEnumTypeValues(SCL scd, String idEnum) throws ScdException { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - DataTypeTemplateAdapter dataTypeTemplateAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); - EnumTypeAdapter enumTypeAdapter = dataTypeTemplateAdapter.getEnumTypeAdapterById(idEnum) - .orElseThrow(() -> new ScdException("Unknown EnumType Id: " + idEnum)); - return enumTypeAdapter.getCurrentElem().getEnumVal().stream() - .map(tEnumVal -> new EnumValDTO(tEnumVal.getOrd(), tEnumVal.getValue())) - .collect(Collectors.toSet()); - } - - /** - * Imports IEDs, DataTypeTemplates and Communication nodes of STD files into SCL (SCD) file - * STD : System Template Definition - * To import STD into SCD, this step are realized - *
      - *
    • Check SCD and STD compatibilities by checking if there is at least one ICD_SYSTEM_VERSION_UUID in - * LNode/Private CompasICDHeader of SCL/Substation/.. not present in IED/Private CompasICDHeader of STD
    • - *
    • List all LNode/Private COMPAS-ICDHeader of SCL/Substation/.. and remove duplicated one with same iedName in order to - * ovoid repetition in actions
    • - *
    • For each Private.ICDSystemVersionUUID and Private.iedName in Substation/ of SCL find corresponding STD File
    • - *
    • import /IED /DataTypeTemplate from that STD file and update IEDName of /IED in SCD file
    • - *
    • import connectedAP and rename ConnectedAP/@iedName in Communication node in SCD file
    • - *
    - * - * @param scd SCL object in which content of STD files are imported - * @param stds list of STD files contenting datas to import into SCD - * @param subNetworkTypes couple of Subnetwork name and possible corresponding ConnectedAP names - * @throws ScdException throws when inconsistency between Substation of SCL content and gien STD files as : - *
      - *
    • ICD_SYSTEM_VERSION_UUID in IED/Private of STD is not present in COMPAS-ICDHeader in Substation/../LNode of SCL
    • - *
    • There are several STD files corresponding to ICD_SYSTEM_VERSION_UUID of COMPAS-ICDHeader in Substation/../LNode of SCL
    • - *
    • There is no STD file found corresponding to COMPAS-ICDHeader in Substation/../LNode of SCL
    • - *
    • COMPAS-ICDHeader is not the same in Substation/../LNode of SCL and in IED/Private of STD
    • - *
    • COMPAS_ICDHEADER in Substation/../LNode of SCL not found in IED/Private of STD
    • - *
    - */ - public static void importSTDElementsInSCD(SCL scd, List stds, List subNetworkTypes) throws ScdException { - - //Check SCD and STD compatibilities - Map mapICDSystemVersionUuidAndSTDFile = PrivateService.createMapICDSystemVersionUuidAndSTDFile(stds); - PrivateService.checkSTDCorrespondanceWithLNodeCompasICDHeader(mapICDSystemVersionUuidAndSTDFile); - // List all Private and remove duplicated one with same iedName - // For each Private.ICDSystemVersionUUID and Private.iedName find STD File - List iedNamesUsed = new ArrayList<>(); - SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - PrivateService.streamIcdHeaders(scd) - .forEach(icdHeader -> { - if (!iedNamesUsed.contains(icdHeader.getIedName())) { - String iedName = icdHeader.getIedName(); - iedNamesUsed.add(iedName); - String icdSysVerUuid = icdHeader.getIcdSystemVersionUUID(); - if (!mapICDSystemVersionUuidAndSTDFile.containsKey(icdSysVerUuid)) - throw new ScdException("There is no STD file found corresponding to " + icdHeader); - // import /ied /dtt in Scd - SCL std = mapICDSystemVersionUuidAndSTDFile.get(icdSysVerUuid).stdList().get(0); - SclRootAdapter stdRootAdapter = new SclRootAdapter(std); - IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); - Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(COMPAS_ICDHEADER.getPrivateType()); - if (optionalTPrivate.isPresent() && optionalTPrivate.flatMap(PrivateService::extractCompasICDHeader).map(IcdHeader::new).get().equals(icdHeader)) { - PrivateService.copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(optionalTPrivate.get(), icdHeader.toTCompasICDHeader()); - } else throw new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED"); - scdRootAdapter.addIED(std, iedName); - - //import connectedAP and rename ConnectedAP/@iedName - TCommunication communication = stdRootAdapter.getCurrentElem().getCommunication(); - List subNetworkDTOSet = SubNetworkDTO.createDefaultSubnetwork(iedName, communication, subNetworkTypes); - addSubnetworks(scdRootAdapter.getCurrentElem(), subNetworkDTOSet, std); - } - }); - } - - - /** - * Removes all ControlBlocks and DataSets for all LNs in SCL - * - * @param scl SCL file for which ControlBlocks and DataSets should be deleted - */ - public static void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final SCL scl) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scl); - List lDeviceAdapters = sclRootAdapter.streamIEDAdapters() - .flatMap(IEDAdapter::streamLDeviceAdapters).toList(); - - // LN0 - lDeviceAdapters.stream() - .map(LDeviceAdapter::getLN0Adapter) - .forEach(ln0 -> { - ln0.removeAllControlBlocksAndDatasets(); - ln0.removeAllExtRefSourceBindings(); - }); - - // Other LN - lDeviceAdapters.stream() - .map(LDeviceAdapter::getLNAdapters).flatMap(List::stream) - .forEach(LNAdapter::removeAllControlBlocksAndDatasets); - } - - /** - * Activate used LDevice and Deactivate unused LDevice in {@link TLNode TLNode } - * - * @param scd SCL file for which LDevice should be activated or deactivated - * @return list of encountered errors - */ - public static List updateLDeviceStatus(SCL scd) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - SubstationAdapter substationAdapter = sclRootAdapter.getSubstationAdapter(); - final List> iedNameLdInstList = substationAdapter.getIedAndLDeviceNamesForLN0FromLNode(); - return sclRootAdapter.streamIEDAdapters() - .flatMap(IEDAdapter::streamLDeviceAdapters) - .map(LDeviceAdapter::getLN0Adapter) - .map(ln0Adapter -> ln0Adapter.updateLDeviceStatus(iedNameLdInstList)) - .flatMap(Optional::stream) - .toList(); - } - - /** - * Checks Control Blocks, DataSets and FCDA number limitation into Access Points - * - * @param scd SCL file for which LDevice should be activated or deactivated - * @return list of encountered errors - */ - public static List analyzeDataGroups(SCL scd) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - return sclRootAdapter.streamIEDAdapters() - .map(iedAdapter -> { - List list = new ArrayList<>(); - list.addAll(iedAdapter.checkDataGroupCoherence()); - list.addAll(iedAdapter.checkBindingDataGroupCoherence()); - return list; - }).flatMap(Collection::stream).toList(); - } - - /** - * Update DAIs of DO InRef in all LN0 of the SCD using matching ExtRef information. - * - * @param scd SCL file for which DOs InRef should be updated with matching ExtRef information - * @return list of encountered errors - */ - public static List updateDoInRef(SCL scd) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - return sclRootAdapter.streamIEDAdapters() - .flatMap(IEDAdapter::streamLDeviceAdapters) - .map(LDeviceAdapter::getLN0Adapter) - .map(LN0Adapter::updateDoInRef) - .flatMap(List::stream) - .toList(); - } - - /** - * Update and/or create Monitoring LNs (LSVS and LGOS) for bound GOOSE and SMV Control Blocks - * - * @param scd SCL file for which LNs (LSVS and LGOS) should be updated and/or created in each LDevice LDSUIED with matching ExtRef information - * @return list of encountered errors - */ - public static List manageMonitoringLns(SCL scd) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - return sclRootAdapter.streamIEDAdapters() - .filter(iedAdapter -> !iedAdapter.getName().contains(IED_TEST_NAME)) - .map(IEDAdapter::manageMonitoringLns) - .flatMap(List::stream) - .toList(); - } -} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AccessPointAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AccessPointAdapter.java index bc54fe6bf..07b6167cd 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AccessPointAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AccessPointAdapter.java @@ -17,7 +17,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.lfenergy.compas.sct.commons.scl.ExtRefService.filterDuplicatedExtRefs; +import static org.lfenergy.compas.sct.commons.ExtRefService.filterDuplicatedExtRefs; /** * A representation of the model object diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapter.java index 997adcc84..9d2d5e104 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapter.java @@ -12,7 +12,7 @@ import org.lfenergy.compas.sct.commons.dto.SclReportItem; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.ObjectReference; -import org.lfenergy.compas.sct.commons.scl.PrivateService; +import org.lfenergy.compas.sct.commons.util.PrivateUtils; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.util.MonitoringLnClassEnum; @@ -322,7 +322,7 @@ public Optional getPrivateHeader(String privateType) { * @return value of private compas:Bay if present, empty Optional otherwise */ public Optional getPrivateCompasBay() { - return PrivateService.extractCompasPrivate(currentElem, TCompasBay.class); + return PrivateUtils.extractCompasPrivate(currentElem, TCompasBay.class); } /** @@ -374,7 +374,7 @@ private Stream streamAccessPointAdapters() { * @return COMPAS-ICDHeader private value if present, else empty Optional */ public Optional getCompasICDHeader() { - return PrivateService.extractCompasPrivate(currentElem, TCompasICDHeader.class); + return PrivateUtils.extractCompasPrivate(currentElem, TCompasICDHeader.class); } /** @@ -383,7 +383,7 @@ public Optional getCompasICDHeader() { * @return COMPAS-SystemVersion private value if present, else empty Optional */ public Optional getCompasSystemVersion() { - return PrivateService.extractCompasPrivate(currentElem, TCompasSystemVersion.class); + return PrivateUtils.extractCompasPrivate(currentElem, TCompasSystemVersion.class); } /** diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapter.java index e932bd816..645241c3d 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapter.java @@ -11,10 +11,10 @@ import org.lfenergy.compas.sct.commons.dto.DataAttributeRef; import org.lfenergy.compas.sct.commons.dto.SclReportItem; import org.lfenergy.compas.sct.commons.exception.ScdException; -import org.lfenergy.compas.sct.commons.scl.ExtRefService; -import org.lfenergy.compas.sct.commons.scl.PrivateService; +import org.lfenergy.compas.sct.commons.util.PrivateUtils; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.ExtRefService; import org.lfenergy.compas.sct.commons.util.ControlBlockEnum; import org.lfenergy.compas.sct.commons.util.FcdaCandidates; import org.lfenergy.compas.sct.commons.util.LdeviceStatus; @@ -136,7 +136,7 @@ private Optional updateExtRefIedName(TExtRef extRef, IEDAdapter s clearBinding(extRef); return sourceValidationError; } - String sourceIedName = PrivateService.extractCompasPrivate(sourceIed.getCurrentElem(), TCompasICDHeader.class) + String sourceIedName = PrivateUtils.extractCompasPrivate(sourceIed.getCurrentElem(), TCompasICDHeader.class) .map(TCompasICDHeader::getIEDName).orElse(""); extRef.setIedName(sourceIedName); compasFlow.setExtRefiedName(sourceIedName); @@ -226,7 +226,7 @@ private String extRefXPath(String extRefDesc) { * @return list of matching CompasFlows */ private List getMatchingCompasFlows(TExtRef extRef) { - return PrivateService.extractCompasPrivates(currentElem, TCompasFlow.class) + return PrivateUtils.extractCompasPrivates(currentElem, TCompasFlow.class) .filter(compasFlow -> isMatchingExtRef(compasFlow, extRef)) .toList(); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LN0Adapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LN0Adapter.java index 8c2bb9b4e..98d8e8b0c 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LN0Adapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LN0Adapter.java @@ -10,7 +10,7 @@ import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.scl.LDeviceActivation; import org.lfenergy.compas.sct.commons.scl.ObjectReference; -import org.lfenergy.compas.sct.commons.scl.PrivateService; +import org.lfenergy.compas.sct.commons.util.PrivateUtils; import java.util.List; import java.util.Optional; @@ -187,7 +187,7 @@ public Optional updateLDeviceStatus(List> ie return Optional.of(buildFatalReportItem("The LDevice doesn't have a DO @name='Beh' OR its associated DA@fc='ST' AND DA@name='stVal'")); } Set enumValues = getEnumValues(daiBehList.get(0).getDaName().getType()); - Optional optionalTCompasLDevice = PrivateService.extractCompasPrivate(getParentAdapter().getCurrentElem(), TCompasLDevice.class); + Optional optionalTCompasLDevice = PrivateUtils.extractCompasPrivate(getParentAdapter().getCurrentElem(), TCompasLDevice.class); if (optionalTCompasLDevice.isEmpty()) { return Optional.of(buildFatalReportItem("The LDevice doesn't have a Private compas:LDevice.")); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/FcdaCsvHelper.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/FcdaCsvHelper.java index aec1aea4a..1c47ecd81 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/FcdaCsvHelper.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/FcdaCsvHelper.java @@ -13,11 +13,11 @@ import java.util.List; /** - * This class is a helper method to load FCDA from a CSV file for use with {@link org.lfenergy.compas.sct.commons.scl.HmiService#createAllHmiReportControlBlocks} + * This class is a helper method to load FCDA from a CSV file for use with {@link IHmiService#createAllHmiReportControlBlocks} * Use the getter to access the list of parsed FCDA. * * @see CsvUtils - * @see org.lfenergy.compas.sct.commons.scl.HmiService#createAllHmiReportControlBlocks + * @see IHmiService#createAllHmiReportControlBlocks */ public class FcdaCsvHelper { diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/PrivateService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/PrivateUtils.java similarity index 89% rename from sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/PrivateService.java rename to sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/PrivateUtils.java index 54b3a2880..8c9ddd26d 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/PrivateService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/PrivateUtils.java @@ -2,13 +2,14 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl; +package org.lfenergy.compas.sct.commons.util; import lombok.NonNull; +import lombok.experimental.UtilityClass; import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.dto.PrivateLinkedToStds; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.icd.IcdHeader; -import org.lfenergy.compas.sct.commons.util.PrivateEnum; import javax.xml.bind.JAXBElement; import java.util.*; @@ -19,25 +20,18 @@ import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_ICDHEADER; /** - * A representation of the {@link PrivateService PrivateService}. + * A representation of the {@link PrivateUtils PrivateService}. *

    * The following features are supported: *

    *
      - *
    1. {@link PrivateService#extractCompasPrivates(TBaseElement, Class) + *
    2. {@link PrivateUtils#extractCompasPrivates(TBaseElement, Class) * Returns the value of the TPrivate containment reference list from given TBaseElement By class type}
    3. - * - *
    4. {@link PrivateService#extractCompasPrivates(TBaseElement, Class)} - * Returns the value of the TPrivate containment reference list from given TPrivate elements By class type} - *
    5. *
    * @see org.lfenergy.compas.scl2007b4.model.TPrivate */ -public final class PrivateService { - - private PrivateService() { - throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); - } +@UtilityClass +public final class PrivateUtils { private static final ObjectFactory objectFactory = new ObjectFactory(); @@ -195,28 +189,23 @@ private static TPrivate createPrivate(JAXBElement jaxbElement) { * @return map of ICD_SYSTEM_VERSION_UUID attribute in IED/Private:COMPAS-ICDHeader and related Private coupled with * all corresponding STD */ - public static Map createMapICDSystemVersionUuidAndSTDFile(List stds) { - Map icdSysVerToPrivateStdsMap = new HashMap<>(); + public static Map createMapICDSystemVersionUuidAndSTDFile(List stds) { + Map icdSysVerToPrivateStdsMap = new HashMap<>(); stds.forEach(std -> std.getIED() .forEach(ied -> ied.getPrivate() .forEach(tp -> - PrivateService.extractCompasICDHeader(tp) + PrivateUtils.extractCompasICDHeader(tp) .map(TCompasICDHeader::getICDSystemVersionUUID) .ifPresent(icdSysVer -> { - PrivateLinkedToSTDs privateLinkedToSTDs = icdSysVerToPrivateStdsMap.get(icdSysVer); - List list = privateLinkedToSTDs != null ? privateLinkedToSTDs.stdList() : new ArrayList<>(); + PrivateLinkedToStds privateLinkedToStds = icdSysVerToPrivateStdsMap.get(icdSysVer); + List list = privateLinkedToStds != null ? privateLinkedToStds.stdList() : new ArrayList<>(); list.add(std); - icdSysVerToPrivateStdsMap.put(icdSysVer, new PrivateLinkedToSTDs(tp, list)); + icdSysVerToPrivateStdsMap.put(icdSysVer, new PrivateLinkedToStds(tp, list)); }) ))); return icdSysVerToPrivateStdsMap; } - - public record PrivateLinkedToSTDs (TPrivate tPrivate, List stdList) { - } - - /** * Checks SCD and STD compatibilities by checking if there is at least one ICD_SYSTEM_VERSION_UUID in * Substation/../LNode/Private COMPAS-ICDHeader of SCL not present in IED/Private COMPAS-ICDHeader of STD @@ -225,9 +214,9 @@ public record PrivateLinkedToSTDs (TPrivate tPrivate, List stdList) { * @throws ScdException throws when there are several STD files corresponding to ICD_SYSTEM_VERSION_UUID * from Substation/../LNode/Private COMPAS-ICDHeader of SCL */ - public static void checkSTDCorrespondanceWithLNodeCompasICDHeader(Map mapICDSystemVersionUuidAndSTDFile) throws ScdException { + public static void checkSTDCorrespondanceWithLNodeCompasICDHeader(Map mapICDSystemVersionUuidAndSTDFile) throws ScdException { mapICDSystemVersionUuidAndSTDFile.values().stream() - .filter(privateLinkedToSTDs -> privateLinkedToSTDs.stdList().size() != 1) + .filter(privateLinkedToStds -> privateLinkedToStds.stdList().size() != 1) .findFirst() .ifPresent(pToStd -> { throw new ScdException("There are several STD files corresponding to " + stdCheckFormatExceptionMessage(pToStd.tPrivate())); @@ -242,7 +231,7 @@ public static void checkSTDCorrespondanceWithLNodeCompasICDHeader(Map optionalCompasICDHeader = PrivateService.extractCompasICDHeader(key); + Optional optionalCompasICDHeader = PrivateUtils.extractCompasICDHeader(key); return HEADER_ID + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getHeaderId).orElse(null) + " " + HEADER_VERSION + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getHeaderVersion).orElse(null) + " " + HEADER_REVISION + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getHeaderRevision).orElse(null) + @@ -265,7 +254,7 @@ public static Stream streamIcdHeaders(SCL scd) { .map(TBay::getFunction).flatMap(Collection::stream) .map(TFunction::getLNode).flatMap(Collection::stream) .map(TLNode::getPrivate).flatMap(Collection::stream) - .map(PrivateService::extractCompasICDHeader) + .map(PrivateUtils::extractCompasICDHeader) .filter(Optional::isPresent) .map(Optional::get) .map(IcdHeader::new); @@ -280,9 +269,9 @@ public static Stream streamIcdHeaders(SCL scd) { * @throws ScdException throws when Private is not COMPAS_ICDHEADER one */ public static boolean comparePrivateCompasICDHeaders(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { - TCompasICDHeader iedCompasICDHeader = PrivateService.extractCompasICDHeader(iedPrivate) + TCompasICDHeader iedCompasICDHeader = PrivateUtils.extractCompasICDHeader(iedPrivate) .orElseThrow(() -> new ScdException(COMPAS_ICDHEADER + "not found in IED Private ")); - TCompasICDHeader scdCompasICDHeader = PrivateService.extractCompasICDHeader(scdPrivate) + TCompasICDHeader scdCompasICDHeader = PrivateUtils.extractCompasICDHeader(scdPrivate) .orElseThrow(() -> new ScdException(COMPAS_ICDHEADER + "not found in LNode Private ")); return Objects.equals(iedCompasICDHeader.getIEDType(), scdCompasICDHeader.getIEDType()) && Objects.equals(iedCompasICDHeader.getICDSystemVersionUUID(), scdCompasICDHeader.getICDSystemVersionUUID()) diff --git a/sct-commons/src/test/java/org/lfenergy/compas/scl2007b4/model/NamespaceConfigurationTest.java b/sct-commons/src/test/java/org/lfenergy/compas/scl2007b4/model/NamespaceConfigurationTest.java index a4b413b91..1b7606cd3 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/scl2007b4/model/NamespaceConfigurationTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/scl2007b4/model/NamespaceConfigurationTest.java @@ -5,7 +5,7 @@ package org.lfenergy.compas.scl2007b4.model; import org.junit.jupiter.api.Test; -import org.lfenergy.compas.sct.commons.scl.PrivateService; +import org.lfenergy.compas.sct.commons.util.PrivateUtils; import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper; import static org.assertj.core.api.Assertions.assertThat; @@ -16,7 +16,7 @@ class NamespaceConfigurationTest { void marshalling_SCL_and_Compas_Privates_should_set_correct_prefix() { // Given SCL scl = createValidScl(); - TPrivate aCompasPrivate = PrivateService.createPrivate(TCompasSclFileType.SCD); + TPrivate aCompasPrivate = PrivateUtils.createPrivate(TCompasSclFileType.SCD); scl.getPrivate().add(aCompasPrivate); // When String result = MarshallerWrapper.marshall(scl); diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ExtRefServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefServiceTest.java similarity index 82% rename from sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ExtRefServiceTest.java rename to sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefServiceTest.java index a30628ff8..d7093b917 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ExtRefServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefServiceTest.java @@ -2,16 +2,20 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl; +package org.lfenergy.compas.sct.commons; +import org.assertj.core.api.Assertions; import org.assertj.core.groups.Tuple; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; 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.*; import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.ied.AbstractLNAdapter; import org.lfenergy.compas.sct.commons.scl.ied.DataSetAdapter; import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; @@ -20,7 +24,10 @@ import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; import org.lfenergy.compas.sct.commons.util.CsvUtils; import org.lfenergy.compas.sct.commons.util.ILDEPFSettings; +import org.lfenergy.compas.sct.commons.util.PrivateUtils; import org.lfenergy.compas.sct.commons.util.SettingLDEPFCsvHelper; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; import java.io.InputStream; import java.io.InputStreamReader; @@ -33,16 +40,20 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 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.scl.ExtRefService.filterDuplicatedExtRefs; import static org.lfenergy.compas.sct.commons.testhelpers.SclHelper.*; import static org.lfenergy.compas.sct.commons.util.CommonConstants.*; import static org.lfenergy.compas.sct.commons.util.ControlBlockEnum.*; import static org.lfenergy.compas.sct.commons.util.SclConstructorHelper.newDurationInMilliSec; +@ExtendWith(MockitoExtension.class) class ExtRefServiceTest { + @InjectMocks + ExtRefService extRefService; + 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-"; @@ -56,7 +67,7 @@ void updateAllExtRefIedNames_should_update_iedName_and_ExtRefIedName() { // Given : An ExtRef with a matching compas:Flow SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_success.xml"); // When - ExtRefService.updateAllExtRefIedNames(scd); + extRefService.updateAllExtRefIedNames(scd); // Then TExtRef extRef = findExtRef(scd, "IED_NAME1", "LD_INST11", "STAT_LDSUIED_LPDO 1 Sortie_13_BOOLEAN_18_stVal_1"); assertThat(extRef.getIedName()).isEqualTo("IED_NAME2"); @@ -65,7 +76,7 @@ void updateAllExtRefIedNames_should_update_iedName_and_ExtRefIedName() { .getLN0Adapter() .getCurrentElem() .getInputs(); - assertThat(PrivateService.extractCompasPrivate(inputs, TCompasFlow.class)) + Assertions.assertThat(PrivateUtils.extractCompasPrivate(inputs, TCompasFlow.class)) .map(TCompasFlow::getExtRefiedName) .hasValue("IED_NAME2"); } @@ -75,7 +86,7 @@ void updateAllExtRefIedNames_should_return_success_status() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_success.xml"); // When - List sclReportItems = ExtRefService.updateAllExtRefIedNames(scd); + List sclReportItems = extRefService.updateAllExtRefIedNames(scd); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)) .overridingErrorMessage(String.valueOf(sclReportItems)) @@ -87,7 +98,7 @@ void updateAllExtRefIedNames_should_return_success_status() { void updateAllExtRefIedNames_should_report_errors(String testCase, SCL scl, SclReportItem... errors) { // Given : scl parameter // When - List sclReportItems = ExtRefService.updateAllExtRefIedNames(scl); + List sclReportItems = extRefService.updateAllExtRefIedNames(scl); // Then : the sclReport should report all errors described in the comments in the SCD file assertThat(sclReportItems).isNotNull(); assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isFalse(); @@ -161,7 +172,7 @@ void updateAllExtRefIedNames_when_not_bindable_should_clear_binding() { // Given : see comments in SCD file SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml"); // When - ExtRefService.updateAllExtRefIedNames(scd); + extRefService.updateAllExtRefIedNames(scd); // Then assertExtRefIsNotBound(findExtRef(scd, "IED_NAME1", "LD_INST12", "ExtRef target LDevice status is off")); assertExtRefIsNotBound(findExtRef(scd, "IED_NAME1", "LD_INST11", "Match compas:Flow but FlowStatus is INACTIVE")); @@ -176,7 +187,7 @@ void updateAllExtRefIedNames_when_lDevice_off_should_remove_binding() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml"); // When - List sclReportItems = ExtRefService.updateAllExtRefIedNames(scd); + List sclReportItems = extRefService.updateAllExtRefIedNames(scd); // Then assertThat(sclReportItems).isNotNull(); LDeviceAdapter lDeviceAdapter = findLDeviceByLdName(scd, "IED_NAME1LD_INST12"); @@ -190,7 +201,7 @@ void updateAllExtRefIedNames_when_FlowStatus_INACTIVE_should_remove_binding() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml"); // When - List sclReportItems = ExtRefService.updateAllExtRefIedNames(scd); + List sclReportItems = extRefService.updateAllExtRefIedNames(scd); // Then assertThat(sclReportItems).isNotNull(); LDeviceAdapter lDeviceAdapter = findLDeviceByLdName(scd, "IED_NAME1LD_INST11"); @@ -208,7 +219,7 @@ void createDataSetAndControlBlocks_should_create_DataSet() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When - List sclReportItems = ExtRefService.createDataSetAndControlBlocks(scd); + List sclReportItems = extRefService.createDataSetAndControlBlocks(scd); // Then assertThat(sclReportItems).isEmpty(); assertThat(streamAllDataSets(scd)).hasSize(6); @@ -239,7 +250,7 @@ void createDataSetAndControlBlocks_should_create_ControlBlocks() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When - List sclReportItems = ExtRefService.createDataSetAndControlBlocks(scd); + List sclReportItems = extRefService.createDataSetAndControlBlocks(scd); // Then assertThat(sclReportItems).isEmpty(); @@ -272,7 +283,7 @@ void createDataSetAndControlBlocks_should_set_ExtRef_srcXXX_attributes() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When - List sclReportItems = ExtRefService.createDataSetAndControlBlocks(scd); + List sclReportItems = extRefService.createDataSetAndControlBlocks(scd); // Then assertThat(sclReportItems).isEmpty(); @@ -301,7 +312,7 @@ void createDataSetAndControlBlocks_when_targetIedName_is_provided_should_succeed // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When - List sclReportItems = ExtRefService.createDataSetAndControlBlocks(scd, "IED_NAME1"); + List sclReportItems = extRefService.createDataSetAndControlBlocks(scd, "IED_NAME1"); // Then assertThat(sclReportItems).isEmpty(); assertThat(streamAllDataSets(scd)).hasSize(6); @@ -317,7 +328,7 @@ void createDataSetAndControlBlocks_when_targetIedName_is_provided_and_no_ext_ref // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When - List sclReportItems = ExtRefService.createDataSetAndControlBlocks(scd, "IED_NAME2"); + List sclReportItems = extRefService.createDataSetAndControlBlocks(scd, "IED_NAME2"); // Then assertThat(sclReportItems).isEmpty(); assertThat(streamAllDataSets(scd)).isEmpty(); @@ -328,7 +339,7 @@ void createDataSetAndControlBlocks_when_targetIedName_is_not_found_should_throw_ // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When & Then - assertThatThrownBy(() -> ExtRefService.createDataSetAndControlBlocks(scd, "non_existing_IED_name")) + assertThatThrownBy(() -> extRefService.createDataSetAndControlBlocks(scd, "non_existing_IED_name")) .isInstanceOf(ScdException.class) .hasMessage("IED.name 'non_existing_IED_name' not found in SCD"); } @@ -338,7 +349,7 @@ void createDataSetAndControlBlocks_when_targetIedName_and_targetLDeviceInst_is_p // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When - List sclReportItems = ExtRefService.createDataSetAndControlBlocks(scd, "IED_NAME1", "LD_INST11"); + List sclReportItems = extRefService.createDataSetAndControlBlocks(scd, "IED_NAME1", "LD_INST11"); // Then assertThat(sclReportItems).isEmpty(); } @@ -348,7 +359,7 @@ void createDataSetAndControlBlocks_when_targetIedName_is_not_found_and_targetLDe // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When & Then - assertThatThrownBy(() -> ExtRefService.createDataSetAndControlBlocks(scd, "non_existing_IED_name", "LD_INST11")) + assertThatThrownBy(() -> extRefService.createDataSetAndControlBlocks(scd, "non_existing_IED_name", "LD_INST11")) .isInstanceOf(ScdException.class) .hasMessage("IED.name 'non_existing_IED_name' not found in SCD"); } @@ -358,7 +369,7 @@ void createDataSetAndControlBlocks_when_targetIedName_and_targetLDeviceInst_is_n // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When & Then - assertThatThrownBy(() -> ExtRefService.createDataSetAndControlBlocks(scd, "IED_NAME1", "non_existing_LDevice_inst")) + assertThatThrownBy(() -> extRefService.createDataSetAndControlBlocks(scd, "IED_NAME1", "non_existing_LDevice_inst")) .isInstanceOf(ScdException.class) .hasMessage("LDevice.inst 'non_existing_LDevice_inst' not found in IED 'IED_NAME1'"); } @@ -368,7 +379,7 @@ void createDataSetAndControlBlocks_when_targetLDeviceInst_is_provided_without_ta // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success.xml"); // When & Then - assertThatThrownBy(() -> ExtRefService.createDataSetAndControlBlocks(scd, null, "LD_INST11")) + assertThatThrownBy(() -> extRefService.createDataSetAndControlBlocks(scd, null, "LD_INST11")) .isInstanceOf(ScdException.class) .hasMessage("IED.name parameter is missing"); } @@ -394,7 +405,7 @@ void updateAllSourceDataSetsAndControlBlocks_should_sort_FCDA_inside_DataSet_and // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_dataset_and_controlblocks_success_test_fcda_sort.xml"); // When - List sclReportItems = ExtRefService.createDataSetAndControlBlocks(scd); + List sclReportItems = extRefService.createDataSetAndControlBlocks(scd); // Then assertThat(sclReportItems).isEmpty(); DataSetAdapter dataSetAdapter = findDataSet(scd, "IED_NAME2", "LD_INST21", "DS_LD_INST21_GSI"); @@ -418,7 +429,7 @@ void configureNetworkForAllControlBlocks_should_create_GSE_and_SMV_elements() { ControlBlockNetworkSettings controlBlockNetworkSettings = controlBlockAdapter -> new SettingsOrError(new Settings(0x1D6, (byte) 4, minTime, maxTime), null); // When - List sclReportItems = ExtRefService.configureNetworkForAllControlBlocks(scd, controlBlockNetworkSettings, RANGES_PER_CB_TYPE); + List sclReportItems = extRefService.configureNetworkForAllControlBlocks(scd, controlBlockNetworkSettings, RANGES_PER_CB_TYPE); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); TConnectedAP connectedAP = new SclRootAdapter(scd).findConnectedApAdapter("IED_NAME2", "AP_NAME").get().getCurrentElem(); @@ -460,7 +471,7 @@ void configureNetworkForAllControlBlocks_should_create_GSE_with_incremental_appi TDurationInMilliSec maxTime = newDurationInMilliSec(2000); ControlBlockNetworkSettings controlBlockNetworkSettings = controlBlockAdapter -> new SettingsOrError(new Settings(0x1D6, (byte) 4, minTime, maxTime), null); // When - List sclReportItems = ExtRefService.configureNetworkForAllControlBlocks(scd, controlBlockNetworkSettings, RANGES_PER_CB_TYPE); + List sclReportItems = extRefService.configureNetworkForAllControlBlocks(scd, controlBlockNetworkSettings, RANGES_PER_CB_TYPE); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); assertThat(streamAllConnectedApGseP(scd, "APPID")) @@ -477,7 +488,7 @@ void configureNetworkForAllControlBlocks_should_fail_when_no_settings_for_this_c // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml"); // When - List sclReportItems = ExtRefService.configureNetworkForAllControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType); + List sclReportItems = extRefService.configureNetworkForAllControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isFalse(); assertThat(sclReportItems) @@ -521,7 +532,7 @@ void filterDuplicatedExtRefs_should_remove_duplicated_extrefs() { List tExtRefList = List.of(tExtRef, tExtRefLnClass, createExtRefExample("CB", TServiceType.GOOSE), createExtRefExample("CB", TServiceType.GOOSE)); // When - List result = ExtRefService.filterDuplicatedExtRefs(tExtRefList); + List result = extRefService.filterDuplicatedExtRefs(tExtRefList); // Then assertThat(result).hasSizeLessThan(tExtRefList.size()) .hasSize(2); @@ -541,7 +552,7 @@ void filterDuplicatedExtRefs_should_not_remove_not_duplicated_extrefs() { List tExtRefList = List.of(tExtRefIedName, tExtRefLdInst, tExtRefLnInst, tExtRefPrefix, createExtRefExample("CB_1", TServiceType.GOOSE), createExtRefExample("CB_1", TServiceType.SMV)); // When - List result = filterDuplicatedExtRefs(tExtRefList); + List result = extRefService.filterDuplicatedExtRefs(tExtRefList); // Then assertThat(result).hasSameSizeAs(tExtRefList) .hasSize(6); @@ -570,7 +581,7 @@ void manageBindingForLDEPF_should_return_noReportAndExtRefUpdateSuccessfully_whe .build(); // When - List sclReportItems = ExtRefService.manageBindingForLDEPF(scd, settingLDEPFCsvHelper); + List sclReportItems = extRefService.manageBindingForLDEPF(scd, settingLDEPFCsvHelper); // Then assertThat(sclReportItems).isEmpty(); TExtRef extRef1 = findExtRef(scd, "IED_NAME1", "LDEPF", "DYN_LDEPF_DIGITAL CHANNEL 1_1_BOOLEEN_1_general_1"); @@ -614,7 +625,6 @@ void manageBindingForLDEPF_should_return_noReportAndExtRefUpdateSuccessfully_whe } - @Test void manageBindingForLDEPF_should_return_no_report_when_extRef_withDifferentIedType_update_successfully() { String fileName = "LDEPF_Setting_file.csv"; @@ -623,7 +633,7 @@ void manageBindingForLDEPF_should_return_no_report_when_extRef_withDifferentIedT SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_extref_with_BCU_BPU.xml"); SettingLDEPFCsvHelper settingLDEPFCsvHelper = new SettingLDEPFCsvHelper(reader); // When - List sclReportItems = ExtRefService.manageBindingForLDEPF(scd, settingLDEPFCsvHelper); + List sclReportItems = extRefService.manageBindingForLDEPF(scd, settingLDEPFCsvHelper); // Then assertThat(sclReportItems).isEmpty(); SclTestMarshaller.assertIsMarshallable(new SclRootAdapter(scd).getCurrentElem()); @@ -701,7 +711,7 @@ void manageBindingForLDEPF_should_return_report_when_manyIedSourceFound() { SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_manyIedSources_in_same_bay.xml"); ILDEPFSettings settings = new SettingLDEPFCsvHelper(reader); // When - List sclReportItems = ExtRefService.manageBindingForLDEPF(scd, settings); + List sclReportItems = extRefService.manageBindingForLDEPF(scd, settings); // Then assertThat(sclReportItems).hasSize(2) .extracting(SclReportItem::message) @@ -743,7 +753,7 @@ void manageBindingForLDEPF_should_return_no_report_when_extRefInFlowKindInternal SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ldepf/scd_ldepf_dataTypeTemplateValid.xml"); SettingLDEPFCsvHelper settingLDEPFCsvHelper = new SettingLDEPFCsvHelper(reader); // When - List sclReportItems = ExtRefService.manageBindingForLDEPF(scd, settingLDEPFCsvHelper); + List sclReportItems = extRefService.manageBindingForLDEPF(scd, settingLDEPFCsvHelper); // Then assertThat(sclReportItems).isEmpty(); SclTestMarshaller.assertIsMarshallable(scd); @@ -804,4 +814,156 @@ private LDEPFSettingData getLDEPFSettingByAnalogNum(List setti .findFirst().get(); } + @Test + void updateExtRefSource_shouldThrowScdException_whenSignalInfoNullOrInvalid() { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setHolderIEDName("IED_NAME2"); + extRefInfo.setHolderLDInst("LD_INST21"); + extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); + + //When Then + assertThat(extRefInfo.getSignalInfo()).isNull(); + assertThatThrownBy(() -> extRefService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // signal = null + extRefInfo.setSignalInfo(new ExtRefSignalInfo()); + assertThat(extRefInfo.getSignalInfo()).isNotNull(); + assertThatThrownBy(() -> extRefService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class);// signal invalid + } + + @Test + void updateExtRefSource_shouldThrowScdException_whenBindingInfoNullOrInvalid() { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setHolderIEDName("IED_NAME2"); + extRefInfo.setHolderLDInst("LD_INST21"); + extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); + + ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); + extRefSignalInfo.setIntAddr("INT_ADDR21"); + extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); + extRefSignalInfo.setPDO("Do21.sdo21"); + extRefInfo.setSignalInfo(extRefSignalInfo); + //When Then + assertThat(extRefInfo.getBindingInfo()).isNull(); + assertThatThrownBy(() -> extRefService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // binding = null + extRefInfo.setBindingInfo(new ExtRefBindingInfo()); + assertThat(extRefInfo.getBindingInfo()).isNotNull(); + assertThatThrownBy(() -> extRefService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class);// binding invalid + } + + @Test + void updateExtRefSource_shouldThrowScdException_whenBindingInternalByIedName() { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setHolderIEDName("IED_NAME2"); + extRefInfo.setHolderLDInst("LD_INST21"); + extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); + + ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); + extRefSignalInfo.setIntAddr("INT_ADDR21"); + extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); + extRefSignalInfo.setPDO("Do21.sdo21"); + extRefInfo.setSignalInfo(extRefSignalInfo); + + ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); + extRefBindingInfo.setIedName("IED_NAME2"); // internal binding + extRefBindingInfo.setLdInst("LD_INST12"); + extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); + extRefInfo.setBindingInfo(new ExtRefBindingInfo()); + //When Then + assertThatThrownBy(() -> extRefService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // CB not allowed + } + + @Test + void updateExtRefSource_shouldThrowScdException_whenBindingInternaByServiceType() { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setHolderIEDName("IED_NAME2"); + extRefInfo.setHolderLDInst("LD_INST21"); + extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); + + ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); + extRefSignalInfo.setIntAddr("INT_ADDR21"); + extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); + extRefSignalInfo.setPDO("Do21.sdo21"); + extRefInfo.setSignalInfo(extRefSignalInfo); + + ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); + extRefBindingInfo.setIedName("IED_NAME2"); // internal binding + extRefBindingInfo.setLdInst("LD_INST12"); + extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); + extRefBindingInfo.setServiceType(TServiceType.POLL); + extRefInfo.setBindingInfo(new ExtRefBindingInfo()); + //When Then + assertThatThrownBy(() -> extRefService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // CB not allowed + } + + @Test + void updateExtRefSource_shouldThrowScdException_whenSourceInfoNullOrInvalid() { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setHolderIEDName("IED_NAME2"); + extRefInfo.setHolderLDInst("LD_INST21"); + extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); + + ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); + extRefSignalInfo.setIntAddr("INT_ADDR21"); + extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); + extRefSignalInfo.setPDO("Do21.sdo21"); + extRefInfo.setSignalInfo(extRefSignalInfo); + + ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); + extRefBindingInfo.setIedName("IED_NAME1"); // internal binding + extRefBindingInfo.setLdInst("LD_INST12"); + extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); + extRefInfo.setBindingInfo(new ExtRefBindingInfo()); + + //When Then + assertThat(extRefInfo.getSourceInfo()).isNull(); + assertThatThrownBy(() -> extRefService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // signal = null + extRefInfo.setSourceInfo(new ExtRefSourceInfo()); + assertThat(extRefInfo.getSourceInfo()).isNotNull(); + assertThatThrownBy(() -> extRefService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class);// signal invalid + } + + @Test + void updateExtRefSource_shouldThrowScdException_whenBindingExternalBinding() { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setHolderIEDName("IED_NAME2"); + extRefInfo.setHolderLDInst("LD_INST21"); + extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); + + ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); + extRefSignalInfo.setIntAddr("INT_ADDR21"); + extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); + extRefSignalInfo.setPDO("Do21.sdo21"); + extRefInfo.setSignalInfo(extRefSignalInfo); + + ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); + extRefBindingInfo.setIedName("IED_NAME1"); + extRefBindingInfo.setLdInst("LD_INST12"); + extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); + extRefInfo.setBindingInfo(extRefBindingInfo); + + ExtRefSourceInfo sourceInfo = new ExtRefSourceInfo(); + sourceInfo.setSrcLDInst(extRefInfo.getBindingInfo().getLdInst()); + sourceInfo.setSrcLNClass(extRefInfo.getBindingInfo().getLnClass()); + sourceInfo.setSrcCBName("goose1"); + extRefInfo.setSourceInfo(sourceInfo); + + //When + TExtRef extRef = assertDoesNotThrow(() -> extRefService.updateExtRefSource(scd, extRefInfo)); + //Then + assertThat(extRef.getSrcCBName()).isEqualTo(extRefInfo.getSourceInfo().getSrcCBName()); + assertThat(extRef.getSrcLDInst()).isEqualTo(extRefInfo.getBindingInfo().getLdInst()); + assertThat(extRef.getSrcLNClass()).contains(extRefInfo.getBindingInfo().getLnClass()); + } + } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/HmiServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/HmiServiceTest.java similarity index 93% rename from sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/HmiServiceTest.java rename to sct-commons/src/test/java/org/lfenergy/compas/sct/commons/HmiServiceTest.java index 5cf61c0b4..a13a86efb 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/HmiServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/HmiServiceTest.java @@ -2,9 +2,10 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl; +package org.lfenergy.compas.sct.commons; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.scl.ied.DataSetAdapter; import org.lfenergy.compas.sct.commons.scl.ied.LN0Adapter; @@ -12,6 +13,8 @@ import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; import org.lfenergy.compas.sct.commons.util.CommonConstants; import org.lfenergy.compas.sct.commons.util.LdeviceStatus; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; @@ -19,15 +22,19 @@ import static org.lfenergy.compas.sct.commons.testhelpers.SclHelper.*; import static org.lfenergy.compas.sct.commons.util.SclConstructorHelper.newFcda; +@ExtendWith(MockitoExtension.class) class HmiServiceTest { + @InjectMocks + HmiService hmiService; + @Test void createAllIhmReportControlBlocks_with_fc_ST_should_create_dataset_and_controlblock() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-hmi-create-report-cb/scd_create_dataset_and_controlblocks_for_hmi.xml"); TFCDA fcda = newFcda("LdInst11", "ANCR", "1", null, "DoName1", null, TFCEnum.ST); // When - HmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); + hmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); // Then // Check DataSet is created DataSetAdapter dataSet = findDataSet(scd, "IedName1", "LdInst11", "DS_LDINST11_DQPO"); @@ -53,7 +60,7 @@ void createAllIhmReportControlBlocks_with_fc_MX_should_create_dataset_and_contro SCL scd = SclTestMarshaller.getSCLFromFile("/scd-hmi-create-report-cb/scd_create_dataset_and_controlblocks_for_hmi.xml"); TFCDA fcda = newFcda("LdInst11", "PVOC", "1", null, "DoName2", null, TFCEnum.MX); // When - HmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); + hmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); // Then // Check DataSet is created DataSetAdapter dataSet = findDataSet(scd, "IedName1", "LdInst11", "DS_LDINST11_CYPO"); @@ -80,7 +87,7 @@ void createAllIhmReportControlBlocks_with_FCDA_on_ln0_should_create_dataset_and_ SCL scd = SclTestMarshaller.getSCLFromFile("/scd-hmi-create-report-cb/scd_create_dataset_and_controlblocks_for_hmi.xml"); TFCDA fcda = newFcda("LdInst11", "LLN0", null, null, "DoName0", null, TFCEnum.ST); // When - HmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); + hmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); // Then // Check DataSet is created DataSetAdapter dataSet = findDataSet(scd, "IedName1", "LdInst11", "DS_LDINST11_DQPO"); @@ -108,7 +115,7 @@ void createAllIhmReportControlBlocks_when_lDevice_ON_but_LN_Mod_StVal_missing_sh ln.getCurrentElem().unsetDOI(); TFCDA fcda = newFcda("LdInst11", "ANCR", "1", null, "DoName1", null, TFCEnum.ST); // When - HmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); + hmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); // Then // Check DataSet is created DataSetAdapter dataSet = findDataSet(scd, "IedName1", "LdInst11", "DS_LDINST11_DQPO"); @@ -132,7 +139,7 @@ void createAllIhmReportControlBlocks_when_lDevice_ON_but_LN_Mod_StVal_OFF_should assertThat(ln.getDaiModStValValue()).hasValue("off"); TFCDA fcda = newFcda("LdInst11", "ANCR", "1", null, "DoName1", null, TFCEnum.ST); // When - HmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); + hmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); // Then assertThat(streamAllDataSets(scd)).isEmpty(); assertThat(streamAllControlBlocks(scd, TReportControl.class)).isEmpty(); @@ -147,7 +154,7 @@ void createAllIhmReportControlBlocks_when_lDevice_OFF_should_not_create_dataset( assertThat(findLDevice(scd, "IedName1", "LdInst11").getLDeviceStatus()).hasValue(LdeviceStatus.OFF.getValue()); TFCDA fcda = newFcda("LdInst11", "ANCR", "1", null, "DoName1", null, TFCEnum.ST); // When - HmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); + hmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); // Then assertThat(streamAllDataSets(scd)).isEmpty(); assertThat(streamAllControlBlocks(scd, TReportControl.class)).isEmpty(); @@ -162,7 +169,7 @@ void createAllIhmReportControlBlocks_when_LDevice_has_no_status_should_not_creat assertThat(findLDevice(scd, "IedName1", "LdInst11").getLDeviceStatus()).isEmpty(); TFCDA fcda = newFcda("LdInst11", "ANCR", "1", null, "DoName1", null, TFCEnum.ST); // When - HmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); + hmiService.createAllHmiReportControlBlocks(scd, List.of(fcda)); // Then assertThat(streamAllDataSets(scd)).isEmpty(); assertThat(streamAllControlBlocks(scd, TReportControl.class)).isEmpty(); diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SclEditorServiceTest.java similarity index 50% rename from sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclServiceTest.java rename to sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SclEditorServiceTest.java index 54d598e9a..0b660677e 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SclEditorServiceTest.java @@ -2,11 +2,11 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl; +package org.lfenergy.compas.sct.commons; -import org.apache.commons.lang3.StringUtils; import org.assertj.core.groups.Tuple; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.CsvSource; @@ -14,25 +14,29 @@ import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.ied.*; import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; -import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDa; -import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDo; import static org.lfenergy.compas.sct.commons.testhelpers.SclHelper.LD_SUIED; import static org.lfenergy.compas.sct.commons.testhelpers.SclHelper.getDAIAdapters; import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_SCL_FILE_TYPE; -class SclServiceTest { +@ExtendWith(MockitoExtension.class) +class SclEditorServiceTest { + + @InjectMocks + SclEditorService sclEditorService; private static Stream sclProviderMissingRequiredObjects() { SCL scl1 = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_KO_MissingBeh.scd"); @@ -92,7 +96,7 @@ void testAddHistoryItem() throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter("hId", SclRootAdapter.VERSION, SclRootAdapter.REVISION); SCL scd = sclRootAdapter.getCurrentElem(); - SclService.addHistoryItem(scd, "who", "what", "why"); + sclEditorService.addHistoryItem(scd, "who", "what", "why"); assertNotNull(scd.getHeader()); THeader.History history = scd.getHeader().getHistory(); @@ -115,7 +119,7 @@ void testAddIED() { assertNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); SCL icd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd)); + assertDoesNotThrow(() -> sclEditorService.addIED(scd, "IED_NAME1", icd)); assertEquals("IED_NAME1", scd.getIED().get(0).getName()); assertNotNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); @@ -129,7 +133,7 @@ void testAddSubnetworks() { assertNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); SCL icd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd)); + assertDoesNotThrow(() -> sclEditorService.addIED(scd, "IED_NAME1", icd)); SubNetworkDTO subNetworkDTO = new SubNetworkDTO(); subNetworkDTO.setName("sName1"); @@ -137,7 +141,7 @@ void testAddSubnetworks() { ConnectedApDTO connectedApDTO = new ConnectedApDTO("IED_NAME1", "AP_NAME"); subNetworkDTO.addConnectedAP(connectedApDTO); - assertDoesNotThrow(() -> SclService.addSubnetworks(scd, List.of(subNetworkDTO), icd)); + assertDoesNotThrow(() -> sclEditorService.addSubnetworks(scd, List.of(subNetworkDTO), icd)); assertIsMarshallable(scd); } @@ -148,588 +152,17 @@ void testAddSubnetworksWithoutCommunicationTagInIcd() { assertNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); SCL icd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd)); + assertDoesNotThrow(() -> sclEditorService.addIED(scd, "IED_NAME1", icd)); - assertDoesNotThrow(() -> SclService.addSubnetworks(scd, List.of(), icd)); + assertDoesNotThrow(() -> sclEditorService.addSubnetworks(scd, List.of(), icd)); String marshalledScd = assertIsMarshallable(scd); assertThat(marshalledScd).doesNotContain(" SclService.addIED(scd, "IED_NAME1", icd)); - - List subNetworkDTOSet = SclService.getSubnetwork(icd); - assertDoesNotThrow(() -> SclService.addSubnetworks(scd, subNetworkDTOSet, icd)); - - String marshalledScd = assertIsMarshallable(scd); - assertThat(marshalledScd).contains("
    ", "PhysConn"); - } - - @Test - void testAddSubnetworksWithoutImportingIcdAddressAndPhysConn() { - SclRootAdapter sclRootAdapter = new SclRootAdapter("hId", SclRootAdapter.VERSION, SclRootAdapter.REVISION); - SCL scd = sclRootAdapter.getCurrentElem(); - assertNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); - SCL icd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_with_filled_communication.xml"); - - assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd)); - - List subNetworkDTOSet = SclService.getSubnetwork(icd); - assertDoesNotThrow(() -> SclService.addSubnetworks(scd, subNetworkDTOSet, null)); - - String marshalledScd = assertIsMarshallable(scd); - assertThat(marshalledScd).doesNotContain("
    ", "PhysConn"); - } - - @Test - void testGetSubnetwork() { - SclRootAdapter sclRootAdapter = new SclRootAdapter("hId", SclRootAdapter.VERSION, SclRootAdapter.REVISION); - SCL scd = sclRootAdapter.getCurrentElem(); - assertNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); - SCL icd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - - assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd)); - - SubNetworkDTO subNetworkDTO = new SubNetworkDTO(); - subNetworkDTO.setName("sName1"); - subNetworkDTO.setType("IP"); - ConnectedApDTO connectedApDTO = new ConnectedApDTO("IED_NAME1", "AP_NAME"); - subNetworkDTO.addConnectedAP(connectedApDTO); - - assertDoesNotThrow(() -> SclService.addSubnetworks(scd, List.of(subNetworkDTO), icd)); - - List subNetworkDTOS = assertDoesNotThrow(() -> SclService.getSubnetwork(scd)); - assertEquals(1, subNetworkDTOS.size()); - } - - @Test - void testGetExtRefInfo() { - SclRootAdapter sclRootAdapter = new SclRootAdapter("hId", SclRootAdapter.VERSION, SclRootAdapter.REVISION); - SCL scd = sclRootAdapter.getCurrentElem(); - assertNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); - SCL icd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - - assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd)); - var extRefInfos = assertDoesNotThrow(() -> SclService.getExtRefInfo(scd, "IED_NAME1", "LD_INST11")); - assertEquals(1, extRefInfos.size()); - - assertEquals("IED_NAME1", extRefInfos.get(0).getHolderIEDName()); - - assertThrows(ScdException.class, () -> SclService.getExtRefInfo(scd, "IED_NAME1", "UNKNOWN_LD")); - } - - @Test - void getExtRefBinders_shouldThowScdException_whenExtRefNotExist() { - //Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_binders_test.xml"); - - ExtRefSignalInfo signalInfo = createSignalInfo("Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11"); - signalInfo.setPLN("ANCR"); - //When Then - assertThatThrownBy( - () -> SclService.getExtRefBinders(scd, "IED_NAME1", "UNKNOWN_LD", "LLN0", "", "", signalInfo)) - .isInstanceOf(ScdException.class); - } - - @Test - void getExtRefBinders_shouldReturnSortedListBindingInfo_whenExtRefAndDOExist() { - // Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_binders_test.xml"); - - ExtRefSignalInfo signalInfo = createSignalInfo( - "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" - ); - signalInfo.setPLN("ANCR"); - - // When - List potentialBinders = SclService.getExtRefBinders(scd, "IED_NAME1", "LD_INST11", "LLN0", "", "", signalInfo); - - // Then - assertThat(potentialBinders).hasSize(4); - assertThat(potentialBinders) - .extracting(ExtRefBindingInfo::getIedName) - .containsExactly("IED_NAME1", "IED_NAME1", "IED_NAME2", "IED_NAME3"); - assertThat(potentialBinders) - .extracting(ExtRefBindingInfo::getLdInst) - .containsExactly("LD_INST11", "LD_INST12", "LD_INST22", "LD_INST31"); - assertThat(potentialBinders) - .extracting(ExtRefBindingInfo::getLnClass) - .containsExactly("ANCR", "ANCR", "ANCR", "ANCR"); - assertThat(potentialBinders) - .extracting(ExtRefBindingInfo::getLnInst) - .containsExactly("1", "1", "2", "3"); - } - - @Test - void testUpdateExtRefBinders() { - SclRootAdapter sclRootAdapter = new SclRootAdapter("hId", SclRootAdapter.VERSION, SclRootAdapter.REVISION); - SCL scd = sclRootAdapter.getCurrentElem(); - assertNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); - SCL icd1 = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - SCL icd2 = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_2_test.xml"); - - assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd1)); - assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME2", icd2)); - - ExtRefSignalInfo signalInfo = createSignalInfo( - "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" - ); - signalInfo.setPServT(null); - signalInfo.setPLN(null); - signalInfo.setDesc(null); - // Signal for external binding (in IED 2 LD_INST22 - PIOC) - ExtRefBindingInfo bindingInfo = new ExtRefBindingInfo(); - bindingInfo.setIedName("IED_NAME2"); - bindingInfo.setLdInst("LD_INST22"); - bindingInfo.setLnClass("PIOC"); - bindingInfo.setLnInst("1"); - bindingInfo.setLnType("LN2"); - bindingInfo.setDoName(new DoTypeName(signalInfo.getPDO())); - bindingInfo.setDaName(new DaTypeName(signalInfo.getPDA())); - bindingInfo.setServiceType(signalInfo.getPServT()); - LNodeDTO lNodeDTO = new LNodeDTO(); - lNodeDTO.setNodeClass(TLLN0Enum.LLN_0.value()); - ExtRefInfo extRefInfo = new ExtRefInfo(); - extRefInfo.setHolderIEDName("IED_NAME1"); - extRefInfo.setHolderLDInst("LD_INST11"); - extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - extRefInfo.setSignalInfo(signalInfo); - extRefInfo.setBindingInfo(bindingInfo); - lNodeDTO.getExtRefs().add(extRefInfo); - - assertDoesNotThrow( - () -> SclService.updateExtRefBinders(scd, extRefInfo) - ); - - extRefInfo.setHolderLDInst("UNKNOWN_LD"); - assertThrows( - ScdException.class, - () -> SclService.updateExtRefBinders(scd, extRefInfo) - ); - assertIsMarshallable(scd); - } - - @Test - void getExtRefSourceInfo_shouldReturnEmptyList_whenExtRefMatchNoFCDA() { - //Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); - String iedName = "IED_NAME2"; - String ldInst = "LD_INST21"; - String lnClass = TLLN0Enum.LLN_0.value(); - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); - LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(() -> iedAdapter.findLDeviceAdapterByLdInst(ldInst).get()); - LN0Adapter ln0Adapter = lDeviceAdapter.getLN0Adapter(); - List extRefs = ln0Adapter.getExtRefs(null); - assertFalse(extRefs.isEmpty()); - - ExtRefInfo extRefInfo = new ExtRefInfo(extRefs.get(0)); - - extRefInfo.setHolderIEDName(iedName); - extRefInfo.setHolderLDInst(ldInst); - extRefInfo.setHolderLnClass(lnClass); - - //When - List controlBlocks = SclService.getExtRefSourceInfo(scd, extRefInfo); - - //Then - assertThat(controlBlocks).isEmpty(); - } - - @Test - void getExtRefSourceInfo_shouldReturnListOfControlBlocks_whenExtRefMatchFCDA() { - //Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/issue_175_scd_get_cbs_test.xml"); - String iedName = "IED_NAME2"; - String ldInst = "LD_INST21"; - String lnClass = TLLN0Enum.LLN_0.value(); - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); - LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(() -> iedAdapter.findLDeviceAdapterByLdInst(ldInst).get()); - LN0Adapter ln0Adapter = lDeviceAdapter.getLN0Adapter(); - List extRefs = ln0Adapter.getExtRefs(null); - assertFalse(extRefs.isEmpty()); - - ExtRefInfo extRefInfo = new ExtRefInfo(extRefs.get(0)); - - extRefInfo.setHolderIEDName(iedName); - extRefInfo.setHolderLDInst(ldInst); - extRefInfo.setHolderLnClass(lnClass); - - //When - List controlBlocks = SclService.getExtRefSourceInfo(scd, extRefInfo); - - //Then - assertThat(controlBlocks).hasSize(1); - assertThat(controlBlocks.get(0).getName()).isEqualTo("goose2"); - } - - @Test - void updateExtRefSource_shouldThrowScdException_whenSignalInfoNullOrInvalid() { - //Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); - ExtRefInfo extRefInfo = new ExtRefInfo(); - extRefInfo.setHolderIEDName("IED_NAME2"); - extRefInfo.setHolderLDInst("LD_INST21"); - extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - - //When Then - assertThat(extRefInfo.getSignalInfo()).isNull(); - assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // signal = null - extRefInfo.setSignalInfo(new ExtRefSignalInfo()); - assertThat(extRefInfo.getSignalInfo()).isNotNull(); - assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class);// signal invalid - } - - @Test - void updateExtRefSource_shouldThrowScdException_whenBindingInfoNullOrInvalid() { - //Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); - ExtRefInfo extRefInfo = new ExtRefInfo(); - extRefInfo.setHolderIEDName("IED_NAME2"); - extRefInfo.setHolderLDInst("LD_INST21"); - extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - - ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); - extRefSignalInfo.setIntAddr("INT_ADDR21"); - extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); - extRefSignalInfo.setPDO("Do21.sdo21"); - extRefInfo.setSignalInfo(extRefSignalInfo); - //When Then - assertThat(extRefInfo.getBindingInfo()).isNull(); - assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // binding = null - extRefInfo.setBindingInfo(new ExtRefBindingInfo()); - assertThat(extRefInfo.getBindingInfo()).isNotNull(); - assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class);// binding invalid - } - - @Test - void updateExtRefSource_shouldThrowScdException_whenBindingInternalByIedName() { - //Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); - ExtRefInfo extRefInfo = new ExtRefInfo(); - extRefInfo.setHolderIEDName("IED_NAME2"); - extRefInfo.setHolderLDInst("LD_INST21"); - extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - - ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); - extRefSignalInfo.setIntAddr("INT_ADDR21"); - extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); - extRefSignalInfo.setPDO("Do21.sdo21"); - extRefInfo.setSignalInfo(extRefSignalInfo); - - ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); - extRefBindingInfo.setIedName("IED_NAME2"); // internal binding - extRefBindingInfo.setLdInst("LD_INST12"); - extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); - extRefInfo.setBindingInfo(new ExtRefBindingInfo()); - //When Then - assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // CB not allowed - } - - @Test - void updateExtRefSource_shouldThrowScdException_whenBindingInternaByServiceType() { - //Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); - ExtRefInfo extRefInfo = new ExtRefInfo(); - extRefInfo.setHolderIEDName("IED_NAME2"); - extRefInfo.setHolderLDInst("LD_INST21"); - extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - - ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); - extRefSignalInfo.setIntAddr("INT_ADDR21"); - extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); - extRefSignalInfo.setPDO("Do21.sdo21"); - extRefInfo.setSignalInfo(extRefSignalInfo); - - ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); - extRefBindingInfo.setIedName("IED_NAME2"); // internal binding - extRefBindingInfo.setLdInst("LD_INST12"); - extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); - extRefBindingInfo.setServiceType(TServiceType.POLL); - extRefInfo.setBindingInfo(new ExtRefBindingInfo()); - //When Then - assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // CB not allowed - } - - @Test - void updateExtRefSource_shouldThrowScdException_whenSourceInfoNullOrInvalid() { - //Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); - ExtRefInfo extRefInfo = new ExtRefInfo(); - extRefInfo.setHolderIEDName("IED_NAME2"); - extRefInfo.setHolderLDInst("LD_INST21"); - extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - - ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); - extRefSignalInfo.setIntAddr("INT_ADDR21"); - extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); - extRefSignalInfo.setPDO("Do21.sdo21"); - extRefInfo.setSignalInfo(extRefSignalInfo); - - ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); - extRefBindingInfo.setIedName("IED_NAME1"); // internal binding - extRefBindingInfo.setLdInst("LD_INST12"); - extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); - extRefInfo.setBindingInfo(new ExtRefBindingInfo()); - - //When Then - assertThat(extRefInfo.getSourceInfo()).isNull(); - assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // signal = null - extRefInfo.setSourceInfo(new ExtRefSourceInfo()); - assertThat(extRefInfo.getSourceInfo()).isNotNull(); - assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class);// signal invalid - } - - @Test - void updateExtRefSource_shouldThrowScdException_whenBindingExternalBinding() { - //Given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); - ExtRefInfo extRefInfo = new ExtRefInfo(); - extRefInfo.setHolderIEDName("IED_NAME2"); - extRefInfo.setHolderLDInst("LD_INST21"); - extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - - ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); - extRefSignalInfo.setIntAddr("INT_ADDR21"); - extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); - extRefSignalInfo.setPDO("Do21.sdo21"); - extRefInfo.setSignalInfo(extRefSignalInfo); - - ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); - extRefBindingInfo.setIedName("IED_NAME1"); - extRefBindingInfo.setLdInst("LD_INST12"); - extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); - extRefInfo.setBindingInfo(extRefBindingInfo); - - ExtRefSourceInfo sourceInfo = new ExtRefSourceInfo(); - sourceInfo.setSrcLDInst(extRefInfo.getBindingInfo().getLdInst()); - sourceInfo.setSrcLNClass(extRefInfo.getBindingInfo().getLnClass()); - sourceInfo.setSrcCBName("goose1"); - extRefInfo.setSourceInfo(sourceInfo); - - //When - TExtRef extRef = assertDoesNotThrow(() -> SclService.updateExtRefSource(scd, extRefInfo)); - //Then - assertThat(extRef.getSrcCBName()).isEqualTo(extRefInfo.getSourceInfo().getSrcCBName()); - assertThat(extRef.getSrcLDInst()).isEqualTo(extRefInfo.getBindingInfo().getLdInst()); - assertThat(extRef.getSrcLNClass()).contains(extRefInfo.getBindingInfo().getLnClass()); - } - - private ExtRefSignalInfo createSignalInfo(String pDO, String pDA, String intAddr) { - - final String DESC = "DESC"; - final String P_LN = TLLN0Enum.LLN_0.value(); - final String P_SERV_T = "Report"; - - ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); - signalInfo.setDesc(DESC); - signalInfo.setPDA(pDA); - signalInfo.setPDO(pDO); - signalInfo.setPLN(P_LN); - signalInfo.setPServT(TServiceType.fromValue(P_SERV_T)); - signalInfo.setIntAddr(intAddr); - - return signalInfo; - } - - @Test - void getDAI_should_return_all_dai() { - // given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - - // when - Set allResults = SclService.getDAI(scd, "IED_NAME1", "LD_INST12", new DataAttributeRef(), true); - - // then - assertThat(allResults).hasSize(733); - - List resultsWithDa = allResults.stream().filter(rdt -> StringUtils.isNotBlank(rdt.getDaRef())).collect(Collectors.toList()); - assertThat(resultsWithDa).hasSize(733); - - List resultsWithNoBda = allResults.stream().filter(rdt -> rdt.getBdaNames().isEmpty()).collect(Collectors.toList()); - assertThat(resultsWithNoBda).hasSize(3); - List resultsWithBdaDepth1 = allResults.stream().filter(rdt -> rdt.getBdaNames().size() == 1).collect(Collectors.toList()); - assertThat(resultsWithBdaDepth1).isEmpty(); - List resultsWithBdaDepth2 = allResults.stream().filter(rdt -> rdt.getBdaNames().size() == 2).collect(Collectors.toList()); - assertThat(resultsWithBdaDepth2).hasSize(1); - List resultsWithBdaDepth3 = allResults.stream().filter(rdt -> rdt.getBdaNames().size() == 3).collect(Collectors.toList()); - assertThat(resultsWithBdaDepth3).hasSize(729); - - - List resultsWithDo = allResults.stream().filter(rdt -> StringUtils.isNotBlank(rdt.getDoRef())).collect(Collectors.toList()); - assertThat(resultsWithDo).hasSize(733); - - List resultsWithNoSdo = allResults.stream().filter(rdt -> rdt.getSdoNames().isEmpty()).collect(Collectors.toList()); - assertThat(resultsWithNoSdo).hasSize(3); - List resultsWithSdoDepth1 = allResults.stream().filter(rdt -> rdt.getSdoNames().size() == 1).collect(Collectors.toList()); - assertThat(resultsWithSdoDepth1).isEmpty(); - List resultsWithSdoDepth2 = allResults.stream().filter(rdt -> rdt.getSdoNames().size() == 2).collect(Collectors.toList()); - assertThat(resultsWithSdoDepth2).hasSize(730); - List resultsWithSdoDepth3 = allResults.stream().filter(rdt -> rdt.getSdoNames().size() == 3).collect(Collectors.toList()); - assertThat(resultsWithSdoDepth3).isEmpty(); - } - - @Test - void getDAI_should_aggregate_attribute_from_DAI() { - // given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_aggregate_DAI.xml"); - - // when - Set dais = SclService.getDAI(scd, "VirtualBCU", "LDMODEXPF", new DataAttributeRef(), false); - - // then - DataAttributeRef lln0 = DataAttributeRef.builder().prefix("").lnType("lntype1").lnClass("LLN0").lnInst("").build(); - DataAttributeRef lln0DoA = lln0.toBuilder().doName(createDo("DoA", TPredefinedCDCEnum.DPL)).build(); - DataAttributeRef lln0DoB = lln0.toBuilder().doName(createDo("DoB", TPredefinedCDCEnum.ACD)).build(); - - assertThat(dais).containsExactlyInAnyOrder( - lln0DoA.toBuilder().daName(createDa("daNotInDai", TFCEnum.CF, false, Map.of(0L, "0"))).build(), - lln0DoA.toBuilder().daName(createDa("daNotInDai2", TFCEnum.CF, true, Map.of())).build(), - lln0DoA.toBuilder().daName(createDa("daiOverrideVal", TFCEnum.CF, false, Map.of(0L, "1"))).build(), - lln0DoA.toBuilder().daName(createDa("daiOverrideValImport", TFCEnum.CF, true, Map.of())).build(), - lln0DoA.toBuilder().daName(createDa("daiOverrideValImport2", TFCEnum.CF, false, Map.of())).build(), - - lln0DoB.toBuilder().daName(createDa("structDa.daNotInDai", TFCEnum.ST, false, Map.of(0L, "0"))).build(), - lln0DoB.toBuilder().daName(createDa("structDa.daNotInDai2", TFCEnum.ST, true, Map.of())).build(), - lln0DoB.toBuilder().daName(createDa("structDa.daiOverrideVal", TFCEnum.ST, false, Map.of(0L, "1"))).build(), - lln0DoB.toBuilder().daName(createDa("structDa.daiOverrideValImport", TFCEnum.ST, true, Map.of())).build(), - lln0DoB.toBuilder().daName(createDa("structDa.daiOverrideValImport2", TFCEnum.ST, false, Map.of())).build(), - - DataAttributeRef.builder().prefix("").lnType("lntype2").lnClass("LPHD").lnInst("0") - .doName(createDo("PhyNam", TPredefinedCDCEnum.DPS)) - .daName(createDa("aDa", TFCEnum.BL, false, Map.of())).build() - ); - } - - @Test - void getDAI_when_LDevice_not_found_should_throw_exception() { - // given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - - // when & then - DataAttributeRef dataAttributeRef = new DataAttributeRef(); - assertThrows(ScdException.class, - () -> SclService.getDAI(scd, "IED_NAME1", "UNKNOWNLD", dataAttributeRef, true)); - } - - @Test - void getDAI_should_filter_updatable_DA() { - // given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); - - // when - Set dais = SclService.getDAI(scd, "VirtualBCU", "LDMODEXPF", new DataAttributeRef(), true); - - // then - assertThat(dais).isNotNull(); - List resultSimpleDa = dais.stream() - .filter(dataAttributeRef -> dataAttributeRef.getBdaNames().isEmpty()) // test only simple DA - .map(DataAttributeRef::getLNRef).collect(Collectors.toList()); - assertThat(resultSimpleDa).containsExactlyInAnyOrder( - // ...AndTrueInDai : If ValImport is True in DAI, DA is updatable - "LLN0.DoA.valImportNotSetAndTrueInDai", - "LLN0.DoA.valImportTrueAndTrueInDai", - "LLN0.DoA.valImportFalseAndTrueInDai", - // valImportTrue : If ValImport is True in DA and DAI does not exist, DA is updatable - "LLN0.DoA.valImportTrue", - // valImportTrueAndNotSetInDai : If ValImport is True in DA and DAI exists but DAI ValImport is not set, DA is updatable - "LLN0.DoA.valImportTrueAndNotSetInDai", - // Only these FC are updatable - "LLN0.DoA.fcCF", - "LLN0.DoA.fcDC", - "LLN0.DoA.fcSG", - "LLN0.DoA.fcSP", - "LLN0.DoA.fcST", - "LLN0.DoA.fcSE" - ); - } - - @Test - void getDAI_should_filter_updatable_BDA() { - // given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); - - // when - Set dais = SclService.getDAI(scd, "VirtualBCU", "LDMODEXPF", new DataAttributeRef(), true); - - // then - assertThat(dais).isNotNull(); - List resultStructDa = dais.stream() - .filter(dataAttributeRef -> !dataAttributeRef.getBdaNames().isEmpty()) // test only struct DA - .map(DataAttributeRef::getLNRef).collect(Collectors.toList()); - assertThat(resultStructDa).containsExactlyInAnyOrder( - // ...AndTrueInDai : If ValImport is True in DAI, BDA is updatable - "LLN0.DoB.structValImportNotSet.bValImportFalseAndTrueInDai", - "LLN0.DoB.structValImportNotSet.bValImportNotSetAndTrueInDai", - "LLN0.DoB.structValImportNotSet.bValImportTrueAndTrueInDai", - "LLN0.DoB.structValImportTrue.bValImportFalseAndTrueInDai", - "LLN0.DoB.structValImportTrue.bValImportNotSetAndTrueInDai", - "LLN0.DoB.structValImportTrue.bValImportTrueAndTrueInDai", - "LLN0.DoB.structValImportFalse.bValImportFalseAndTrueInDai", - "LLN0.DoB.structValImportFalse.bValImportNotSetAndTrueInDai", - "LLN0.DoB.structValImportFalse.bValImportTrueAndTrueInDai", - // bValImportTrue : If ValImport is True in BDA and DAI does not exist, BDA is updatable - "LLN0.DoB.structValImportFalse.bValImportTrue", - "LLN0.DoB.structValImportTrue.bValImportTrue", - "LLN0.DoB.structValImportNotSet.bValImportTrue", - // bValImportTrueAndNotSetInDai : If ValImport is True in BDA and DAI exists but DAI ValImport is not set, BDA is updatable - "LLN0.DoB.structValImportTrue.bValImportTrueAndNotSetInDai", - "LLN0.DoB.structValImportNotSet.bValImportTrueAndNotSetInDai", - "LLN0.DoB.structValImportFalse.bValImportTrueAndNotSetInDai", - // Only these FC are updatable - "LLN0.DoB.structWithFcCF.bda1", - "LLN0.DoB.structWithFcDC.bda1", - "LLN0.DoB.structWithFcSG.bda1", - "LLN0.DoB.structWithFcSP.bda1", - "LLN0.DoB.structWithFcST.bda1", - "LLN0.DoB.structWithFcSE.bda1" - ); - } - - @Test - void getDAI_should_filter_updatable_DA_with_sGroup_Val() { - // given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); - - // when - Set dais = SclService.getDAI(scd, "VirtualBCU", "LDCAP", new DataAttributeRef(), true); - - // then - assertThat(dais).isNotNull(); - List resultSimpleDa = dais.stream() - .filter(dataAttributeRef -> dataAttributeRef.getBdaNames().isEmpty()) // test only simple DA - .map(DataAttributeRef::getLNRef).collect(Collectors.toList()); - assertThat(resultSimpleDa).containsExactlyInAnyOrder( - "LLN0.DoD.sGroupValImportNotSet", - "LLN0.DoD.sGroupValImportTrue" - ); - } - - @Test - void getDAI_should_filter_updatable_DA_with_sGroup_Val_without_ConfSg() { - // given - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); - - // when - Set dais = SclService.getDAI(scd, "VirtualBCU", "LDMOD", new DataAttributeRef(), true); - - // then - assertThat(dais) - .isNotNull() - .isEmpty(); - } - @Test void testInitScl_With_headerId_shouldNotThrowError() { UUID headerId = UUID.randomUUID(); - SCL scd = assertDoesNotThrow(() -> SclService.initScl(headerId, "hVersion", "hRevision")); + SCL scd = assertDoesNotThrow(() -> sclEditorService.initScl(headerId, "hVersion", "hRevision")); assertIsMarshallable(scd); } @@ -738,7 +171,7 @@ void initScl_should_create_Private_SCL_FILETYPE() { // Given UUID headerId = UUID.randomUUID(); // When Then - SCL scd = assertDoesNotThrow(() -> SclService.initScl(headerId, "hVersion", "hRevision")); + SCL scd = assertDoesNotThrow(() -> sclEditorService.initScl(headerId, "hVersion", "hRevision")); assertThat(scd.getPrivate()).isNotEmpty(); assertThat(scd.getPrivate().get(0).getType()).isEqualTo(COMPAS_SCL_FILE_TYPE.getPrivateType()); assertIsMarshallable(scd); @@ -747,11 +180,11 @@ void initScl_should_create_Private_SCL_FILETYPE() { @Test void updateHeader_should_update_header_tag() { //Given - SCL scd = assertDoesNotThrow(() -> SclService.initScl(UUID.randomUUID(), "hVersion", "hRevision")); + SCL scd = assertDoesNotThrow(() -> sclEditorService.initScl(UUID.randomUUID(), "hVersion", "hRevision")); UUID hId = UUID.fromString(scd.getHeader().getId()); HeaderDTO headerDTO = DTO.createHeaderDTO(hId); //When - SclService.updateHeader(scd, headerDTO); + sclEditorService.updateHeader(scd, headerDTO); //Then assertIsMarshallable(scd); } @@ -762,7 +195,7 @@ void testUpdateDAI() { dataAttributeRef.setLnType("unknownID"); SCL scd = SclTestMarshaller.getSCLFromFile("/ied-test-schema-conf/ied_unit_test.xml"); - assertThrows(ScdException.class, () -> SclService.updateDAI( + assertThrows(ScdException.class, () -> sclEditorService.updateDAI( scd, "IED", "LD", dataAttributeRef )); dataAttributeRef.setLnType("LNO1"); @@ -773,24 +206,16 @@ void testUpdateDAI() { TVal tVal = new TVal(); tVal.setValue("newValue"); dataAttributeRef.setDaiValues(List.of(tVal)); - assertDoesNotThrow(() -> SclService.updateDAI(scd, "IED_NAME", "LD_INS1", dataAttributeRef)); + assertDoesNotThrow(() -> sclEditorService.updateDAI(scd, "IED_NAME", "LD_INS1", dataAttributeRef)); assertIsMarshallable(scd); } - @Test - void testGetEnumTypeValues() { - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - assertThrows(ScdException.class, () -> SclService.getEnumTypeValues(scd, "unknwnID")); - var enumList = assertDoesNotThrow(() -> SclService.getEnumTypeValues(scd, "RecCycModKind")); - assertFalse(enumList.isEmpty()); - } - @Test void testImportSTDElementsInSCD() { SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd.xml"); SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); - assertDoesNotThrow(() -> SclService.importSTDElementsInSCD(scd, List.of(std), DTO.SUB_NETWORK_TYPES)); + assertDoesNotThrow(() -> sclEditorService.importSTDElementsInSCD(scd, List.of(std), DTO.SUB_NETWORK_TYPES)); assertThat(scd.getIED()).hasSize(1); assertThat(scd.getDataTypeTemplates()).hasNoNullFieldsOrProperties(); assertThat(scd.getCommunication().getSubNetwork()).hasSize(2); @@ -803,9 +228,8 @@ void testImportSTDElementsInSCD_with_Multiple_STD() { SCL std0 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); SCL std1 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_SITESITE1SCU1.xml"); SCL std2 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_SITESITE1SCU2.xml"); - SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - assertDoesNotThrow(() -> SclService.importSTDElementsInSCD(scd, List.of(std0, std1, std2), DTO.SUB_NETWORK_TYPES)); + assertDoesNotThrow(() -> sclEditorService.importSTDElementsInSCD(scd, List.of(std0, std1, std2), DTO.SUB_NETWORK_TYPES)); assertThat(scd.getIED()).hasSize(3); assertThat(scd.getDataTypeTemplates()).hasNoNullFieldsOrProperties(); assertThat(scd.getCommunication().getSubNetwork()).hasSize(2); @@ -822,7 +246,7 @@ void testImportSTDElementsInSCD_Several_STD_Match_Compas_ICDHeader() { SCL std1 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); //When Then List stds = List.of(std, std1); - assertThrows(ScdException.class, () -> SclService.importSTDElementsInSCD(scd, stds, DTO.SUB_NETWORK_TYPES)); + assertThrows(ScdException.class, () -> sclEditorService.importSTDElementsInSCD(scd, stds, DTO.SUB_NETWORK_TYPES)); assertIsMarshallable(scd); } @@ -832,7 +256,7 @@ void test_importSTDElementsInSCD_should_not_throw_exception_when_SCD_file_contai SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd_with_same_compas_icd_header_in_different_functions.xml"); SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); //When Then - assertDoesNotThrow(() -> SclService.importSTDElementsInSCD(scd, List.of(std), DTO.SUB_NETWORK_TYPES)); + assertDoesNotThrow(() -> sclEditorService.importSTDElementsInSCD(scd, List.of(std), DTO.SUB_NETWORK_TYPES)); assertIsMarshallable(scd); } @@ -841,9 +265,9 @@ void testImportSTDElementsInSCD_Compas_ICDHeader_Not_Match() { //Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd.xml"); SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml"); - SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + List stdList = List.of(std); //When Then - assertThrows(ScdException.class, () -> SclService.importSTDElementsInSCD(scd, List.of(std), DTO.SUB_NETWORK_TYPES)); + assertThrows(ScdException.class, () -> sclEditorService.importSTDElementsInSCD(scd, stdList, DTO.SUB_NETWORK_TYPES)); assertIsMarshallable(scd); } @@ -851,10 +275,9 @@ void testImportSTDElementsInSCD_Compas_ICDHeader_Not_Match() { void testImportSTDElementsInSCD_No_STD_Match() { //Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/ssd.xml"); - SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + List stdList = List.of(); //When Then - Set stds = new HashSet<>(); - assertThrows(ScdException.class, () -> SclService.importSTDElementsInSCD(scd, List.of(), DTO.SUB_NETWORK_TYPES)); + assertThrows(ScdException.class, () -> sclEditorService.importSTDElementsInSCD(scd, stdList, DTO.SUB_NETWORK_TYPES)); assertIsMarshallable(scd); } @@ -863,7 +286,7 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_D // Given SCL scl = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml"); // When - SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); + sclEditorService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); // Then SclRootAdapter scdRootAdapter = new SclRootAdapter(scl); List lDevices = scdRootAdapter.streamIEDAdapters().flatMap(IEDAdapter::streamLDeviceAdapters).toList(); @@ -883,7 +306,7 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_D // Given SCL scl = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml"); // When - SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); + sclEditorService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); // Then SclRootAdapter scdRootAdapter = new SclRootAdapter(scl); List lns = scdRootAdapter.streamIEDAdapters() @@ -903,7 +326,7 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_srcXXX_attributes_o // Given SCL scl = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml"); // When - SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); + sclEditorService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); // Then SclRootAdapter scdRootAdapter = new SclRootAdapter(scl); List extRefs = scdRootAdapter @@ -930,7 +353,7 @@ void updateLDeviceStatus_shouldReturnReportWithError_MissingRequiredObject(Strin assertEquals("off", getLDeviceStatusValue(scl, "IedName1", "LDSUIED").get().getValue()); String before = MarshallerWrapper.marshall(scl); // When - List sclReportItems = SclService.updateLDeviceStatus(scl); + List sclReportItems = sclEditorService.updateLDeviceStatus(scl); // Then String after = MarshallerWrapper.marshall(scl); assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isFalse(); @@ -951,7 +374,7 @@ void updateLDeviceStatus_shouldReturnReportWithError_WhenLDeviceStatusActiveOrUn assertThat(getLDeviceStatusValue(scl, "IedName3", "LDSUIED")).isEmpty(); String before = MarshallerWrapper.marshall(scl); // When - List sclReportItems = SclService.updateLDeviceStatus(scl); + List sclReportItems = sclEditorService.updateLDeviceStatus(scl); // Then String after = MarshallerWrapper.marshall(scl); assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isFalse(); @@ -973,7 +396,7 @@ void updateLDeviceStatus_shouldReturnReportWithError_WhenAllLDeviceInactive_Test assertThat(getLDeviceStatusValue(scl, "IedName2", "LDSUIED").get().getValue()).isEqualTo("on"); assertThat(getLDeviceStatusValue(scl, "IedName3", "LDSUIED")).isEmpty(); // When - List sclReportItems = SclService.updateLDeviceStatus(scl); + List sclReportItems = sclEditorService.updateLDeviceStatus(scl); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isFalse(); assertThat(sclReportItems) @@ -1001,7 +424,7 @@ void updateLDeviceStatus_shouldReturnUpdatedFile() { assertThat(getLDeviceStatusValue(givenScl, "IedName3", "LDSUIED")).isEmpty(); // When - List sclReportItems = SclService.updateLDeviceStatus(givenScl); + List sclReportItems = sclEditorService.updateLDeviceStatus(givenScl); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); assertThat(getLDeviceStatusValue(givenScl, "IedName1", "LDSUIED")).isPresent(); @@ -1032,7 +455,7 @@ void updateLDeviceStatus_shouldReturnUpdatedFile_when_DAI_Mod_DO_stVal_whatever_ .map(TVal::getValue) .hasValue("on"); // When - List sclReportItems = SclService.updateLDeviceStatus(givenScl); + List sclReportItems = sclEditorService.updateLDeviceStatus(givenScl); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); @@ -1075,7 +498,7 @@ void updateDoInRef_shouldReturnUpdatedFile(String testName, String ldInst, Strin SCL givenScl = SclTestMarshaller.getSCLFromFile("/scd-test-update-inref/scd_update_inref_issue_231_test_ok.xml"); // When - List sclReportItems = SclService.updateDoInRef(givenScl); + List sclReportItems = sclEditorService.updateDoInRef(givenScl); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); @@ -1099,7 +522,7 @@ void updateDoInRef_should_not_update_DAI(String testName, String ldInst, String SCL givenScl = SclTestMarshaller.getSCLFromFile("/scd-test-update-inref/scd_update_inref_issue_231_test_ok.xml"); // When - List sclReportItems = SclService.updateDoInRef(givenScl); + List sclReportItems = sclEditorService.updateDoInRef(givenScl); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); @@ -1112,7 +535,7 @@ void updateDoInRef_shouldReturnReportWithError_when_ExtRef_not_coherent() { SCL givenScl = SclTestMarshaller.getSCLFromFile("/scd-test-update-inref/scd_update_inref_issue_231_test_ko.xml"); // When - List sclReportItems = SclService.updateDoInRef(givenScl); + List sclReportItems = sclEditorService.updateDoInRef(givenScl); // Then assertThat(sclReportItems.stream().noneMatch(SclReportItem::isError)).isTrue(); @@ -1146,7 +569,7 @@ void analyzeDataGroups_should_success() { iedAdapter1.getCurrentElem().getAccessPoint().get(0).getServices().getClientServices().setMaxSMV(2L); iedAdapter1.getCurrentElem().getAccessPoint().get(0).getServices().getClientServices().setMaxReports(1L); // When - List sclReportItems = SclService.analyzeDataGroups(scd); + List sclReportItems = sclEditorService.analyzeDataGroups(scd); //Then assertThat(sclReportItems).isEmpty(); @@ -1165,7 +588,7 @@ void analyzeDataGroups_should_return_errors_messages() { iedAdapter.getCurrentElem().getAccessPoint().get(0).getServices().getGOOSE().setMax(2L); iedAdapter.getCurrentElem().getAccessPoint().get(0).getServices().getConfReportControl().setMax(0L); // When - List sclReportItems = SclService.analyzeDataGroups(scd); + List sclReportItems = sclEditorService.analyzeDataGroups(scd); //Then assertThat(sclReportItems).hasSize(11) .extracting(SclReportItem::message) @@ -1188,7 +611,7 @@ void manageMonitoringLns_should_update_and_create_lsvs_and_goose() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/monitoring_lns/scd_monitoring_lsvs_lgos.xml"); // When - List sclReportItems = SclService.manageMonitoringLns(scd); + List sclReportItems = sclEditorService.manageMonitoringLns(scd); //Then assertThat(sclReportItems).isEmpty(); LDeviceAdapter lDeviceAdapter = new SclRootAdapter(scd).getIEDAdapterByName("IED_NAME1").getLDeviceAdapterByLdInst(LD_SUIED); @@ -1210,7 +633,7 @@ void manageMonitoringLns_should_not_update_and_not_create_lsvs_and_goose_when_no LDeviceAdapter lDeviceAdapter21 = sclRootAdapter.getIEDAdapterByName("IED_NAME1").getLDeviceAdapterByLdInst("LD_INST21"); lDeviceAdapter21.getLN0Adapter().getCurrentElem().setInputs(null); // When - List sclReportItems = SclService.manageMonitoringLns(scd); + List sclReportItems = sclEditorService.manageMonitoringLns(scd); //Then assertThat(sclReportItems).isEmpty(); LDeviceAdapter lDeviceAdapter = sclRootAdapter.getIEDAdapterByName("IED_NAME1").getLDeviceAdapterByLdInst(LD_SUIED); @@ -1232,7 +655,7 @@ void manageMonitoringLns_should_not_update_and_not_create_lsvs_and_goose_when_da getDAIAdapters(lDeviceAdapter, "LSVS", "SvCBRef", "setSrcRef") .forEach(daiAdapter -> daiAdapter.getCurrentElem().setValImport(false)); // When - List sclReportItems = SclService.manageMonitoringLns(scd); + List sclReportItems = sclEditorService.manageMonitoringLns(scd); //Then assertThat(sclReportItems) .isNotEmpty() diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SclElementsProviderServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SclElementsProviderServiceTest.java new file mode 100644 index 000000000..487d242f9 --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SclElementsProviderServiceTest.java @@ -0,0 +1,343 @@ +// SPDX-FileCopyrightText: 2021 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons; + +import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.dto.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.scl.ied.*; +import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.*; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDa; +import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDo; + +@ExtendWith(MockitoExtension.class) +class SclElementsProviderServiceTest { + + @InjectMocks + SclElementsProviderService sclElementsProviderService; + + @Test + void getExtRefBinders_shouldThrowScdException_whenExtRefNotExist() { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_binders_test.xml"); + + ExtRefSignalInfo signalInfo = createSignalInfo("Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11"); + signalInfo.setPLN("ANCR"); + //When Then + assertThatThrownBy( + () -> sclElementsProviderService.getExtRefBinders(scd, "IED_NAME1", "UNKNOWN_LD", "LLN0", "", "", signalInfo)) + .isInstanceOf(ScdException.class); + } + + @Test + void getExtRefBinders_shouldReturnSortedListBindingInfo_whenExtRefAndDOExist() { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_binders_test.xml"); + + ExtRefSignalInfo signalInfo = createSignalInfo( + "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" + ); + signalInfo.setPLN("ANCR"); + + // When + List potentialBinders = sclElementsProviderService.getExtRefBinders(scd, "IED_NAME1", "LD_INST11", "LLN0", "", "", signalInfo); + + // Then + assertThat(potentialBinders).hasSize(4); + assertThat(potentialBinders) + .extracting(ExtRefBindingInfo::getIedName) + .containsExactly("IED_NAME1", "IED_NAME1", "IED_NAME2", "IED_NAME3"); + assertThat(potentialBinders) + .extracting(ExtRefBindingInfo::getLdInst) + .containsExactly("LD_INST11", "LD_INST12", "LD_INST22", "LD_INST31"); + assertThat(potentialBinders) + .extracting(ExtRefBindingInfo::getLnClass) + .containsExactly("ANCR", "ANCR", "ANCR", "ANCR"); + assertThat(potentialBinders) + .extracting(ExtRefBindingInfo::getLnInst) + .containsExactly("1", "1", "2", "3"); + } + + @Test + void getExtRefSourceInfo_shouldReturnEmptyList_whenExtRefMatchNoFCDA() { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + String iedName = "IED_NAME2"; + String ldInst = "LD_INST21"; + String lnClass = TLLN0Enum.LLN_0.value(); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(() -> iedAdapter.findLDeviceAdapterByLdInst(ldInst).get()); + LN0Adapter ln0Adapter = lDeviceAdapter.getLN0Adapter(); + List extRefs = ln0Adapter.getExtRefs(null); + assertFalse(extRefs.isEmpty()); + + ExtRefInfo extRefInfo = new ExtRefInfo(extRefs.get(0)); + + extRefInfo.setHolderIEDName(iedName); + extRefInfo.setHolderLDInst(ldInst); + extRefInfo.setHolderLnClass(lnClass); + + //When + List controlBlocks = sclElementsProviderService.getExtRefSourceInfo(scd, extRefInfo); + + //Then + assertThat(controlBlocks).isEmpty(); + } + + @Test + void getExtRefSourceInfo_shouldReturnListOfControlBlocks_whenExtRefMatchFCDA() { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/issue_175_scd_get_cbs_test.xml"); + String iedName = "IED_NAME2"; + String ldInst = "LD_INST21"; + String lnClass = TLLN0Enum.LLN_0.value(); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(() -> iedAdapter.findLDeviceAdapterByLdInst(ldInst).get()); + LN0Adapter ln0Adapter = lDeviceAdapter.getLN0Adapter(); + List extRefs = ln0Adapter.getExtRefs(null); + assertFalse(extRefs.isEmpty()); + + ExtRefInfo extRefInfo = new ExtRefInfo(extRefs.get(0)); + + extRefInfo.setHolderIEDName(iedName); + extRefInfo.setHolderLDInst(ldInst); + extRefInfo.setHolderLnClass(lnClass); + + //When + List controlBlocks = sclElementsProviderService.getExtRefSourceInfo(scd, extRefInfo); + + //Then + assertThat(controlBlocks).hasSize(1); + assertThat(controlBlocks.get(0).getName()).isEqualTo("goose2"); + } + + private ExtRefSignalInfo createSignalInfo(String pDO, String pDA, String intAddr) { + + final String DESC = "DESC"; + final String P_LN = TLLN0Enum.LLN_0.value(); + final String P_SERV_T = "Report"; + + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setDesc(DESC); + signalInfo.setPDA(pDA); + signalInfo.setPDO(pDO); + signalInfo.setPLN(P_LN); + signalInfo.setPServT(TServiceType.fromValue(P_SERV_T)); + signalInfo.setIntAddr(intAddr); + + return signalInfo; + } + + @Test + void getDAI_should_return_all_dai() { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); + + // when + Set allResults = sclElementsProviderService.getDAI(scd, "IED_NAME1", "LD_INST12", new DataAttributeRef(), true); + + // then + assertThat(allResults).hasSize(733); + + List resultsWithDa = allResults.stream().filter(rdt -> StringUtils.isNotBlank(rdt.getDaRef())).collect(Collectors.toList()); + assertThat(resultsWithDa).hasSize(733); + + List resultsWithNoBda = allResults.stream().filter(rdt -> rdt.getBdaNames().isEmpty()).collect(Collectors.toList()); + assertThat(resultsWithNoBda).hasSize(3); + List resultsWithBdaDepth1 = allResults.stream().filter(rdt -> rdt.getBdaNames().size() == 1).collect(Collectors.toList()); + assertThat(resultsWithBdaDepth1).isEmpty(); + List resultsWithBdaDepth2 = allResults.stream().filter(rdt -> rdt.getBdaNames().size() == 2).collect(Collectors.toList()); + assertThat(resultsWithBdaDepth2).hasSize(1); + List resultsWithBdaDepth3 = allResults.stream().filter(rdt -> rdt.getBdaNames().size() == 3).collect(Collectors.toList()); + assertThat(resultsWithBdaDepth3).hasSize(729); + + + List resultsWithDo = allResults.stream().filter(rdt -> StringUtils.isNotBlank(rdt.getDoRef())).collect(Collectors.toList()); + assertThat(resultsWithDo).hasSize(733); + + List resultsWithNoSdo = allResults.stream().filter(rdt -> rdt.getSdoNames().isEmpty()).collect(Collectors.toList()); + assertThat(resultsWithNoSdo).hasSize(3); + List resultsWithSdoDepth1 = allResults.stream().filter(rdt -> rdt.getSdoNames().size() == 1).collect(Collectors.toList()); + assertThat(resultsWithSdoDepth1).isEmpty(); + List resultsWithSdoDepth2 = allResults.stream().filter(rdt -> rdt.getSdoNames().size() == 2).collect(Collectors.toList()); + assertThat(resultsWithSdoDepth2).hasSize(730); + List resultsWithSdoDepth3 = allResults.stream().filter(rdt -> rdt.getSdoNames().size() == 3).collect(Collectors.toList()); + assertThat(resultsWithSdoDepth3).isEmpty(); + } + + @Test + void getDAI_should_aggregate_attribute_from_DAI() { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_aggregate_DAI.xml"); + + // when + Set dais = sclElementsProviderService.getDAI(scd, "VirtualBCU", "LDMODEXPF", new DataAttributeRef(), false); + + // then + DataAttributeRef lln0 = DataAttributeRef.builder().prefix("").lnType("lntype1").lnClass("LLN0").lnInst("").build(); + DataAttributeRef lln0DoA = lln0.toBuilder().doName(createDo("DoA", TPredefinedCDCEnum.DPL)).build(); + DataAttributeRef lln0DoB = lln0.toBuilder().doName(createDo("DoB", TPredefinedCDCEnum.ACD)).build(); + + assertThat(dais).containsExactlyInAnyOrder( + lln0DoA.toBuilder().daName(createDa("daNotInDai", TFCEnum.CF, false, Map.of(0L, "0"))).build(), + lln0DoA.toBuilder().daName(createDa("daNotInDai2", TFCEnum.CF, true, Map.of())).build(), + lln0DoA.toBuilder().daName(createDa("daiOverrideVal", TFCEnum.CF, false, Map.of(0L, "1"))).build(), + lln0DoA.toBuilder().daName(createDa("daiOverrideValImport", TFCEnum.CF, true, Map.of())).build(), + lln0DoA.toBuilder().daName(createDa("daiOverrideValImport2", TFCEnum.CF, false, Map.of())).build(), + + lln0DoB.toBuilder().daName(createDa("structDa.daNotInDai", TFCEnum.ST, false, Map.of(0L, "0"))).build(), + lln0DoB.toBuilder().daName(createDa("structDa.daNotInDai2", TFCEnum.ST, true, Map.of())).build(), + lln0DoB.toBuilder().daName(createDa("structDa.daiOverrideVal", TFCEnum.ST, false, Map.of(0L, "1"))).build(), + lln0DoB.toBuilder().daName(createDa("structDa.daiOverrideValImport", TFCEnum.ST, true, Map.of())).build(), + lln0DoB.toBuilder().daName(createDa("structDa.daiOverrideValImport2", TFCEnum.ST, false, Map.of())).build(), + + DataAttributeRef.builder().prefix("").lnType("lntype2").lnClass("LPHD").lnInst("0") + .doName(createDo("PhyNam", TPredefinedCDCEnum.DPS)) + .daName(createDa("aDa", TFCEnum.BL, false, Map.of())).build() + ); + } + + @Test + void getDAI_when_LDevice_not_found_should_throw_exception() { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); + + // when & then + DataAttributeRef dataAttributeRef = new DataAttributeRef(); + assertThrows(ScdException.class, + () -> sclElementsProviderService.getDAI(scd, "IED_NAME1", "UNKNOWNLD", dataAttributeRef, true)); + } + + @Test + void getDAI_should_filter_updatable_DA() { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); + + // when + Set dais = sclElementsProviderService.getDAI(scd, "VirtualBCU", "LDMODEXPF", new DataAttributeRef(), true); + + // then + assertThat(dais).isNotNull(); + List resultSimpleDa = dais.stream() + .filter(dataAttributeRef -> dataAttributeRef.getBdaNames().isEmpty()) // test only simple DA + .map(DataAttributeRef::getLNRef).collect(Collectors.toList()); + assertThat(resultSimpleDa).containsExactlyInAnyOrder( + // ...AndTrueInDai : If ValImport is True in DAI, DA is updatable + "LLN0.DoA.valImportNotSetAndTrueInDai", + "LLN0.DoA.valImportTrueAndTrueInDai", + "LLN0.DoA.valImportFalseAndTrueInDai", + // valImportTrue : If ValImport is True in DA and DAI does not exist, DA is updatable + "LLN0.DoA.valImportTrue", + // valImportTrueAndNotSetInDai : If ValImport is True in DA and DAI exists but DAI ValImport is not set, DA is updatable + "LLN0.DoA.valImportTrueAndNotSetInDai", + // Only these FC are updatable + "LLN0.DoA.fcCF", + "LLN0.DoA.fcDC", + "LLN0.DoA.fcSG", + "LLN0.DoA.fcSP", + "LLN0.DoA.fcST", + "LLN0.DoA.fcSE" + ); + } + + @Test + void getDAI_should_filter_updatable_BDA() { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); + + // when + Set dais = sclElementsProviderService.getDAI(scd, "VirtualBCU", "LDMODEXPF", new DataAttributeRef(), true); + + // then + assertThat(dais).isNotNull(); + List resultStructDa = dais.stream() + .filter(dataAttributeRef -> !dataAttributeRef.getBdaNames().isEmpty()) // test only struct DA + .map(DataAttributeRef::getLNRef).collect(Collectors.toList()); + assertThat(resultStructDa).containsExactlyInAnyOrder( + // ...AndTrueInDai : If ValImport is True in DAI, BDA is updatable + "LLN0.DoB.structValImportNotSet.bValImportFalseAndTrueInDai", + "LLN0.DoB.structValImportNotSet.bValImportNotSetAndTrueInDai", + "LLN0.DoB.structValImportNotSet.bValImportTrueAndTrueInDai", + "LLN0.DoB.structValImportTrue.bValImportFalseAndTrueInDai", + "LLN0.DoB.structValImportTrue.bValImportNotSetAndTrueInDai", + "LLN0.DoB.structValImportTrue.bValImportTrueAndTrueInDai", + "LLN0.DoB.structValImportFalse.bValImportFalseAndTrueInDai", + "LLN0.DoB.structValImportFalse.bValImportNotSetAndTrueInDai", + "LLN0.DoB.structValImportFalse.bValImportTrueAndTrueInDai", + // bValImportTrue : If ValImport is True in BDA and DAI does not exist, BDA is updatable + "LLN0.DoB.structValImportFalse.bValImportTrue", + "LLN0.DoB.structValImportTrue.bValImportTrue", + "LLN0.DoB.structValImportNotSet.bValImportTrue", + // bValImportTrueAndNotSetInDai : If ValImport is True in BDA and DAI exists but DAI ValImport is not set, BDA is updatable + "LLN0.DoB.structValImportTrue.bValImportTrueAndNotSetInDai", + "LLN0.DoB.structValImportNotSet.bValImportTrueAndNotSetInDai", + "LLN0.DoB.structValImportFalse.bValImportTrueAndNotSetInDai", + // Only these FC are updatable + "LLN0.DoB.structWithFcCF.bda1", + "LLN0.DoB.structWithFcDC.bda1", + "LLN0.DoB.structWithFcSG.bda1", + "LLN0.DoB.structWithFcSP.bda1", + "LLN0.DoB.structWithFcST.bda1", + "LLN0.DoB.structWithFcSE.bda1" + ); + } + + @Test + void getDAI_should_filter_updatable_DA_with_sGroup_Val() { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); + + // when + Set dais = sclElementsProviderService.getDAI(scd, "VirtualBCU", "LDCAP", new DataAttributeRef(), true); + + // then + assertThat(dais).isNotNull(); + List resultSimpleDa = dais.stream() + .filter(dataAttributeRef -> dataAttributeRef.getBdaNames().isEmpty()) // test only simple DA + .map(DataAttributeRef::getLNRef).collect(Collectors.toList()); + assertThat(resultSimpleDa).containsExactlyInAnyOrder( + "LLN0.DoD.sGroupValImportNotSet", + "LLN0.DoD.sGroupValImportTrue" + ); + } + + @Test + void getDAI_should_filter_updatable_DA_with_sGroup_Val_without_ConfSg() { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); + + // when + Set dais = sclElementsProviderService.getDAI(scd, "VirtualBCU", "LDMOD", new DataAttributeRef(), true); + + // then + assertThat(dais) + .isNotNull() + .isEmpty(); + } + + @Test + void testGetEnumTypeValues() { + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); + assertThrows(ScdException.class, () -> sclElementsProviderService.getEnumTypeValues(scd, "unknwnID")); + var enumList = assertDoesNotThrow(() -> sclElementsProviderService.getEnumTypeValues(scd, "RecCycModKind")); + assertFalse(enumList.isEmpty()); + } + +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SubstationServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SubstationServiceTest.java similarity index 79% rename from sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SubstationServiceTest.java rename to sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SubstationServiceTest.java index 1c6d9bbee..9a3bfa060 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SubstationServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/SubstationServiceTest.java @@ -2,29 +2,36 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl; +package org.lfenergy.compas.sct.commons; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TSubstation; import org.lfenergy.compas.scl2007b4.model.TVoltageLevel; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; +@ExtendWith(MockitoExtension.class) class SubstationServiceTest { + @InjectMocks + SubstationService substationService; + @Test void addSubstation_when_SCD_has_no_substation_should_succeed() { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scl-root-test-schema-conf/add_ied_test.xml"); SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); - assertThat(scd.getSubstation().size()).isZero(); + assertThat(scd.getSubstation()).asList().isEmpty(); // When - SubstationService.addSubstation(scd, ssd); + substationService.addSubstation(scd, ssd); // Then assertIsMarshallable(scd); assertThat(scd.getSubstation().size()).isNotZero(); @@ -40,11 +47,11 @@ void addSubstation_when_SCD_has_a_substation_should_succeed() { TSubstation ssdSubstation = ssd.getSubstation().get(0); assertThat(scdSubstation.getVoltageLevel().stream().map(TVoltageLevel::getBay).count()).isEqualTo(1); // When - SubstationService.addSubstation(scd, ssd); + substationService.addSubstation(scd, ssd); // Then assertIsMarshallable(scd); assertThat(scdSubstation.getName()).isEqualTo(ssdSubstation.getName()); - assertThat(scd.getSubstation().size()).isEqualTo(ssd.getSubstation().size()); + assertThat(scd.getSubstation()).asList().hasSameSizeAs(ssd.getSubstation()); assertThat(scdSubstation.getVoltageLevel().stream().map(TVoltageLevel::getBay).count()).isEqualTo(2); } @@ -55,7 +62,7 @@ void addSubstation_when_SSD_with_multiple_Substations_should_throw_exception() { SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_with_2_substations.xml"); // When & Then - assertThrows(ScdException.class, () -> SubstationService.addSubstation(scd, ssd)); + assertThrows(ScdException.class, () -> substationService.addSubstation(scd, ssd)); } @Test @@ -65,7 +72,7 @@ void addSubstation_when_SSD_with_no_substation_should_throw_exception() { SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml"); // When & Then - assertThrows(ScdException.class, () -> SubstationService.addSubstation(scd, ssd)); + assertThrows(ScdException.class, () -> substationService.addSubstation(scd, ssd)); } @Test @@ -74,7 +81,7 @@ void addSubstation_when_substations_names_differ_should_throw_exception() { SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/scd_with_substation_name_different.xml"); SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); // When & Then - assertThrows(ScdException.class, () -> SubstationService.addSubstation(scd, ssd)); + assertThrows(ScdException.class, () -> substationService.addSubstation(scd, ssd)); } } 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 index abd09200f..89450f8d6 100644 --- 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 @@ -14,7 +14,7 @@ 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.scl.PrivateService; +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; @@ -193,7 +193,7 @@ void getNetworkSettings_should_return_null_when_missing_ied_private(PrivateEnum //Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-create-dataset-and-controlblocks/scd_create_controlblock_network_configuration.xml"); SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - PrivateService.removePrivates(findIed(sclRootAdapter.getCurrentElem(), "IED_NAME2").getCurrentElem(), missingPrivate); + 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 diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapterTest.java index 29de7b98b..4d24f57ef 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapterTest.java @@ -14,7 +14,7 @@ import org.lfenergy.compas.sct.commons.dto.SclReportItem; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.ObjectReference; -import org.lfenergy.compas.sct.commons.scl.PrivateService; +import org.lfenergy.compas.sct.commons.util.PrivateUtils; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; import org.lfenergy.compas.sct.commons.util.MonitoringLnClassEnum; @@ -291,7 +291,7 @@ void getCompasICDHeader_should_return_compas_icd_header(){ IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName("IED_NAME"); TCompasICDHeader tCompasICDHeader = new TCompasICDHeader(); tCompasICDHeader.setHeaderId("HEADER_ID"); - iedAdapter.getCurrentElem().getPrivate().add(PrivateService.createPrivate(tCompasICDHeader)); + iedAdapter.getCurrentElem().getPrivate().add(PrivateUtils.createPrivate(tCompasICDHeader)); // When Optional compasICDHeader = iedAdapter.getCompasICDHeader(); @@ -307,7 +307,7 @@ void getCompasSystemVersion_should_return_compas_icd_header(){ IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName("IED_NAME"); TCompasSystemVersion tCompasSystemVersion = new TCompasSystemVersion(); tCompasSystemVersion.setMainSystemVersion("01.00"); - iedAdapter.getCurrentElem().getPrivate().add(PrivateService.createPrivate(tCompasSystemVersion)); + iedAdapter.getCurrentElem().getPrivate().add(PrivateUtils.createPrivate(tCompasSystemVersion)); // When Optional compasSystemVersion = iedAdapter.getCompasSystemVersion(); diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LN0AdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LN0AdapterTest.java index 366c2d64e..000d694d2 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LN0AdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LN0AdapterTest.java @@ -274,8 +274,7 @@ void testGetControlBlocks() { void testGetControlSetByBindingInfo() { LN0 ln0 = new LN0(); - LN0Adapter ln0Adapter = mock(LN0Adapter.class); - ln0Adapter = Mockito.spy(ln0Adapter); + LN0Adapter ln0Adapter = Mockito.spy(new LN0Adapter(null, ln0)); when(ln0Adapter.getCurrentElem()).thenReturn(ln0); diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapterTest.java index 7429cfdca..76f833157 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapterTest.java @@ -8,7 +8,7 @@ import org.junit.platform.commons.support.HierarchyTraversalMode; import org.junit.platform.commons.support.ReflectionSupport; import org.lfenergy.compas.scl2007b4.model.*; -import org.lfenergy.compas.sct.commons.scl.PrivateService; +import org.lfenergy.compas.sct.commons.util.PrivateUtils; import javax.xml.bind.JAXBElement; import javax.xml.namespace.QName; @@ -60,7 +60,7 @@ void addPrivate_should_succeed() { // Given TLNode tlNode = new TLNode(); LNodeAdapter lNodeAdapter = new LNodeAdapter(null, tlNode); - TPrivate tPrivate = PrivateService.createPrivate(TCompasSclFileType.SCD); + TPrivate tPrivate = PrivateUtils.createPrivate(TCompasSclFileType.SCD); // When lNodeAdapter.addPrivate(tPrivate); // Then @@ -87,7 +87,7 @@ void deepCopy_should_succeed() { tText.getContent().add("Text1"); tText.getOtherAttributes().put(QName.valueOf("Text1_attribute1"), "Text1_value1"); tlNode.setText(tText); - tlNode.getPrivate().add(PrivateService.createPrivate(TCompasSclFileType.SCD)); + tlNode.getPrivate().add(PrivateUtils.createPrivate(TCompasSclFileType.SCD)); tlNode.getOtherAttributes().put(QName.valueOf("tlNode_attribute1"), "tlNode_value1"); LNodeAdapter lNodeAdapter = new LNodeAdapter(null, tlNode); // When diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/PrivateServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/PrivateUtilsTest.java similarity index 75% rename from sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/PrivateServiceTest.java rename to sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/PrivateUtilsTest.java index cbee0d90c..6e6148e7c 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/PrivateServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/PrivateUtilsTest.java @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl; +package org.lfenergy.compas.sct.commons.util; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -10,10 +10,10 @@ import org.junit.jupiter.params.provider.MethodSource; import org.junit.platform.commons.support.ReflectionSupport; import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.dto.PrivateLinkedToStds; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.icd.IcdHeader; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; -import org.lfenergy.compas.sct.commons.util.PrivateEnum; import javax.xml.bind.JAXBElement; import java.lang.reflect.Constructor; @@ -26,7 +26,7 @@ import static org.assertj.core.api.Assertions.*; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -class PrivateServiceTest { +class PrivateUtilsTest { private TPrivate privateSCD; private TPrivate privateICD; @@ -46,14 +46,14 @@ void setUp() { @Test void class_should_not_be_instantiable() { // Given - Constructor[] constructors = PrivateService.class.getDeclaredConstructors(); + Constructor[] constructors = PrivateUtils.class.getDeclaredConstructors(); assertThat(constructors).hasSize(1); Constructor constructor = constructors[0]; constructor.setAccessible(true); // When & Then assertThatThrownBy(constructor::newInstance) - .isInstanceOf(InvocationTargetException.class) - .getCause().isInstanceOf(UnsupportedOperationException.class); + .isInstanceOf(InvocationTargetException.class) + .getCause().isInstanceOf(UnsupportedOperationException.class); } @Test @@ -64,11 +64,11 @@ void extractCompasPrivates_should_return_privates_value() { baseElement.getPrivate().add(privateICD); // Given : setUp // When - List result = PrivateService.extractCompasPrivates(baseElement, TCompasSclFileType.class).toList(); + List result = PrivateUtils.extractCompasPrivates(baseElement, TCompasSclFileType.class).toList(); //Then assertThat(result) - .hasSize(2) - .containsExactly(TCompasSclFileType.SCD, TCompasSclFileType.ICD); + .hasSize(2) + .containsExactly(TCompasSclFileType.SCD, TCompasSclFileType.ICD); } @Test @@ -77,7 +77,7 @@ void extractCompasPrivates_when_no_privates_match_class_should_return_empty_list TBaseElement baseElement = new SCL(); baseElement.getPrivate().add(privateSCD); // When - List result = PrivateService.extractCompasPrivates(baseElement, TCompasICDHeader.class).toList(); + List result = PrivateUtils.extractCompasPrivates(baseElement, TCompasICDHeader.class).toList(); //Then assertThat(result).isEmpty(); } @@ -88,7 +88,7 @@ void extractCompasPrivates_when_class_is_not_compas_class_should_throw_exception TBaseElement baseElement = new SCL(); baseElement.getPrivate().add(privateSCD); // When - Stream compasPrivates = PrivateService.extractCompasPrivates(baseElement, Object.class); + Stream compasPrivates = PrivateUtils.extractCompasPrivates(baseElement, Object.class); // Then assertThatCode(compasPrivates::toList) .isInstanceOf(NoSuchElementException.class) @@ -103,7 +103,7 @@ void extractCompasPrivates_when_content_not_match_private_type_should_throw_exce baseElement.getPrivate().add(privateSCD); Class compasClass = PrivateEnum.COMPAS_BAY.getCompasClass(); - Stream stream = PrivateService.extractCompasPrivates(baseElement, compasClass); + Stream stream = PrivateUtils.extractCompasPrivates(baseElement, compasClass); // When & Then assertThatCode(stream::toList) .isInstanceOf(ClassCastException.class) @@ -117,11 +117,11 @@ void extractCompasPrivates_on_base_element_should_return_privates_value() { baseElement.getPrivate().add(privateSCD); baseElement.getPrivate().add(privateICD); // When - List result = PrivateService.extractCompasPrivates(baseElement, TCompasSclFileType.class).toList(); + List result = PrivateUtils.extractCompasPrivates(baseElement, TCompasSclFileType.class).toList(); // Then assertThat(result) - .hasSize(2) - .containsExactly(TCompasSclFileType.SCD, TCompasSclFileType.ICD); + .hasSize(2) + .containsExactly(TCompasSclFileType.SCD, TCompasSclFileType.ICD); } @Test @@ -129,7 +129,7 @@ void extractCompasPrivates_on_base_element_should_not_set_private() { // Given TBaseElement baseElement = new SCL(); // When - PrivateService.extractCompasPrivates(baseElement, TCompasSclFileType.class); + PrivateUtils.extractCompasPrivates(baseElement, TCompasSclFileType.class); // Then assertThat(baseElement.isSetPrivate()).isFalse(); } @@ -140,10 +140,10 @@ void extractCompasPrivate_on_base_element_should_return_private_value() { TBaseElement baseElement = new SCL(); baseElement.getPrivate().add(privateSCD); // When - Optional result = PrivateService.extractCompasPrivate(baseElement, TCompasSclFileType.class); + Optional result = PrivateUtils.extractCompasPrivate(baseElement, TCompasSclFileType.class); //Then assertThat(result).isPresent() - .hasValue(TCompasSclFileType.SCD); + .hasValue(TCompasSclFileType.SCD); } @Test @@ -151,7 +151,7 @@ void extractCompasPrivate_on_base_element_should_return_empty() { // Given TBaseElement baseElement = new SCL(); // When - Optional result = PrivateService.extractCompasPrivate(baseElement, TCompasBay.class); + Optional result = PrivateUtils.extractCompasPrivate(baseElement, TCompasBay.class); //Then assertThat(result).isNotPresent(); } @@ -163,7 +163,7 @@ void extractCompasPrivate_on_base_element_should_throw_exception() { baseElement.getPrivate().add(privateSCD); baseElement.getPrivate().add(privateICD); // When & Then - assertThatCode(() -> PrivateService.extractCompasPrivate(baseElement, TCompasSclFileType.class)) + assertThatCode(() -> PrivateUtils.extractCompasPrivate(baseElement, TCompasSclFileType.class)) .isInstanceOf(ScdException.class) .hasMessage("Expecting maximum 1 element of type class org.lfenergy.compas.scl2007b4.model.TCompasSclFileType in private COMPAS-SclFileType, but got more"); } @@ -176,7 +176,7 @@ void extractCompasICDHeader_should_return_private_value() { TCompasICDHeader tCompasICDHeader = objectFactory.createTCompasICDHeader(); privateSCD.getContent().add(objectFactory.createICDHeader(tCompasICDHeader)); // When - Optional optionalResult = PrivateService.extractCompasICDHeader(privateSCD); + Optional optionalResult = PrivateUtils.extractCompasICDHeader(privateSCD); //Then assertThat(optionalResult).isPresent().get().matches(result -> result == tCompasICDHeader); } @@ -187,7 +187,7 @@ void createPrivate_should_return_private_new_private(Object compasElement) throw // Given PrivateEnum privateEnum = PrivateEnum.fromClass(compasElement.getClass()); assertThat(privateEnum).isNotNull(); - Optional optionalCreatePrivateMethod = ReflectionSupport.findMethod(PrivateService.class, "createPrivate", compasElement.getClass()); + Optional optionalCreatePrivateMethod = ReflectionSupport.findMethod(PrivateUtils.class, "createPrivate", compasElement.getClass()); assertThat(optionalCreatePrivateMethod).isPresent(); Method createPrivateMethod = optionalCreatePrivateMethod.get(); // When @@ -196,19 +196,19 @@ void createPrivate_should_return_private_new_private(Object compasElement) throw assertThat(result).isInstanceOf(TPrivate.class); TPrivate resultPrivate = (TPrivate) result; assertThat(resultPrivate).isNotNull() - .hasFieldOrPropertyWithValue("type", privateEnum.getPrivateType()); + .hasFieldOrPropertyWithValue("type", privateEnum.getPrivateType()); assertThat(resultPrivate.getContent()).hasSize(1).first().satisfies(content -> assertThat(content).isInstanceOf(JAXBElement.class)); JAXBElement content = (JAXBElement) resultPrivate.getContent().get(0); assertThat(content.isNil()).isFalse(); assertThat(content.getValue()).isNotNull().isInstanceOf(compasElement.getClass()) - .isEqualTo(compasElement); + .isEqualTo(compasElement); } public static Stream createPrivateTestSources() { return Stream.of(new TCompasBay(), - new TCompasICDHeader(), - TCompasSclFileType.SCD, - new TCompasSystemVersion()); + new TCompasICDHeader(), + TCompasSclFileType.SCD, + new TCompasSystemVersion()); } @Test @@ -217,7 +217,7 @@ void removePrivates_should_remove_privates() { TBaseElement baseElement = new SCL(); baseElement.getPrivate().add(privateSCD); // When - PrivateService.removePrivates(baseElement, PrivateEnum.COMPAS_SCL_FILE_TYPE); + PrivateUtils.removePrivates(baseElement, PrivateEnum.COMPAS_SCL_FILE_TYPE); // Then assertThat(baseElement.isSetPrivate()).isFalse(); } @@ -228,7 +228,7 @@ void removePrivates_should_do_nothing_when_no_private_match_type() { TBaseElement baseElement = new SCL(); baseElement.getPrivate().add(privateSCD); // When - PrivateService.removePrivates(baseElement, PrivateEnum.COMPAS_ICDHEADER); + PrivateUtils.removePrivates(baseElement, PrivateEnum.COMPAS_ICDHEADER); // Then assertThat(baseElement.getPrivate()).hasSize(1); } @@ -239,9 +239,9 @@ void removePrivates_should_remove_privates_of_given_type() { TBaseElement baseElement = new SCL(); baseElement.getPrivate().add(privateSCD); TCompasICDHeader tCompasICDHeader = objectFactory.createTCompasICDHeader(); - baseElement.getPrivate().add(PrivateService.createPrivate(tCompasICDHeader)); + baseElement.getPrivate().add(PrivateUtils.createPrivate(tCompasICDHeader)); // When - PrivateService.removePrivates(baseElement, PrivateEnum.COMPAS_ICDHEADER); + PrivateUtils.removePrivates(baseElement, PrivateEnum.COMPAS_ICDHEADER); // Then assertThat(baseElement.getPrivate()).hasSize(1); TPrivate tPrivate = baseElement.getPrivate().get(0); @@ -258,7 +258,7 @@ void removePrivates_should_not_set_private() { TBaseElement baseElement = new SCL(); baseElement.unsetPrivate(); // When - PrivateService.removePrivates(baseElement, PrivateEnum.COMPAS_ICDHEADER); + PrivateUtils.removePrivates(baseElement, PrivateEnum.COMPAS_ICDHEADER); // Then assertThat(baseElement.isSetPrivate()).isFalse(); } @@ -269,12 +269,12 @@ void createMapICDSystemVersionUuidAndSTDFile_Should_return_empty_map_when_no_ICD SCL scl1 = new SCL(); TIED tied1 = new TIED(); TCompasICDHeader compasICDHeader1 = new TCompasICDHeader(); - TPrivate tPrivate1 = PrivateService.createPrivate(compasICDHeader1); + TPrivate tPrivate1 = PrivateUtils.createPrivate(compasICDHeader1); tied1.getPrivate().add(tPrivate1); scl1.getIED().add(tied1); //When - Map stringSCLMap = PrivateService.createMapICDSystemVersionUuidAndSTDFile(List.of(scl1)); + Map stringSCLMap = PrivateUtils.createMapICDSystemVersionUuidAndSTDFile(List.of(scl1)); //Then assertThat(stringSCLMap.keySet()).isEmpty(); @@ -296,9 +296,9 @@ void createMapICDSystemVersionUuidAndSTDFile_Should_return_map_with_two_lines() compasICDHeader2.setICDSystemVersionUUID("UUID-2"); TCompasICDHeader compasICDHeader3 = new TCompasICDHeader(); compasICDHeader3.setICDSystemVersionUUID("UUID-2"); - TPrivate tPrivate1 = PrivateService.createPrivate(compasICDHeader1); - TPrivate tPrivate2 = PrivateService.createPrivate(compasICDHeader2); - TPrivate tPrivate3 = PrivateService.createPrivate(compasICDHeader3); + TPrivate tPrivate1 = PrivateUtils.createPrivate(compasICDHeader1); + TPrivate tPrivate2 = PrivateUtils.createPrivate(compasICDHeader2); + TPrivate tPrivate3 = PrivateUtils.createPrivate(compasICDHeader3); tied1.getPrivate().add(tPrivate1); tied2.getPrivate().add(tPrivate2); tied3.getPrivate().add(tPrivate3); @@ -307,7 +307,7 @@ void createMapICDSystemVersionUuidAndSTDFile_Should_return_map_with_two_lines() scl3.getIED().add(tied3); //When - Map stringSCLMap = PrivateService.createMapICDSystemVersionUuidAndSTDFile(List.of(scl1,scl2,scl3)); + Map stringSCLMap = PrivateUtils.createMapICDSystemVersionUuidAndSTDFile(List.of(scl1,scl2,scl3)); //Then assertThat(stringSCLMap.keySet()).hasSize(2).containsExactly("UUID-1", "UUID-2"); @@ -324,18 +324,18 @@ void checkSTDCorrespondanceWithLNodeCompasICDHeadershoul_throw_scdEception(){ compasICDHeader2.setHeaderId("ID-2"); compasICDHeader2.setHeaderVersion("VER-2"); compasICDHeader2.setHeaderRevision("REV-2"); - TPrivate tPrivate1 = PrivateService.createPrivate(compasICDHeader1); - TPrivate tPrivate2 = PrivateService.createPrivate(compasICDHeader2); + TPrivate tPrivate1 = PrivateUtils.createPrivate(compasICDHeader1); + TPrivate tPrivate2 = PrivateUtils.createPrivate(compasICDHeader2); - PrivateService.PrivateLinkedToSTDs privateLinkedToSTDs1 = new PrivateService.PrivateLinkedToSTDs(tPrivate1,Collections.singletonList(new SCL())); - PrivateService.PrivateLinkedToSTDs privateLinkedToSTDs2 = new PrivateService.PrivateLinkedToSTDs(tPrivate2, Arrays.asList(new SCL(), new SCL())); + PrivateLinkedToStds privateLinkedToSTDs1 = new PrivateLinkedToStds(tPrivate1,Collections.singletonList(new SCL())); + PrivateLinkedToStds privateLinkedToSTDs2 = new PrivateLinkedToStds(tPrivate2, Arrays.asList(new SCL(), new SCL())); - Map stringSCLMap = new HashMap<>(); + Map stringSCLMap = new HashMap<>(); stringSCLMap.put("UUID-1", privateLinkedToSTDs1); stringSCLMap.put("UUID-2", privateLinkedToSTDs2); //When Then - assertThatThrownBy(() -> PrivateService.checkSTDCorrespondanceWithLNodeCompasICDHeader(stringSCLMap)) + assertThatThrownBy(() -> PrivateUtils.checkSTDCorrespondanceWithLNodeCompasICDHeader(stringSCLMap)) .isInstanceOf(ScdException.class) .hasMessage("There are several STD files corresponding to headerId = ID-2 headerVersion = VER-2 headerRevision = REV-2 and ICDSystemVersionUUID = UUID-2"); @@ -348,18 +348,18 @@ void checkSTDCorrespondanceWithLNodeCompasICDHeader_should_pass(){ compasICDHeader1.setICDSystemVersionUUID("UUID-1"); TCompasICDHeader compasICDHeader2 = new TCompasICDHeader(); compasICDHeader2.setICDSystemVersionUUID("UUID-2"); - TPrivate tPrivate1 = PrivateService.createPrivate(compasICDHeader1); - TPrivate tPrivate2 = PrivateService.createPrivate(compasICDHeader2); + TPrivate tPrivate1 = PrivateUtils.createPrivate(compasICDHeader1); + TPrivate tPrivate2 = PrivateUtils.createPrivate(compasICDHeader2); - PrivateService.PrivateLinkedToSTDs privateLinkedToSTDs1 = new PrivateService.PrivateLinkedToSTDs(tPrivate1,Collections.singletonList(new SCL())); - PrivateService.PrivateLinkedToSTDs privateLinkedToSTDs2 = new PrivateService.PrivateLinkedToSTDs(tPrivate2, Collections.singletonList(new SCL())); + PrivateLinkedToStds privateLinkedToSTDs1 = new PrivateLinkedToStds(tPrivate1,Collections.singletonList(new SCL())); + PrivateLinkedToStds privateLinkedToSTDs2 = new PrivateLinkedToStds(tPrivate2, Collections.singletonList(new SCL())); - Map stringSCLMap = new HashMap<>(); + Map stringSCLMap = new HashMap<>(); stringSCLMap.put("UUID-1", privateLinkedToSTDs1); stringSCLMap.put("UUID-2", privateLinkedToSTDs2); //When Then - assertDoesNotThrow(() -> PrivateService.checkSTDCorrespondanceWithLNodeCompasICDHeader(stringSCLMap)); + assertDoesNotThrow(() -> PrivateUtils.checkSTDCorrespondanceWithLNodeCompasICDHeader(stringSCLMap)); } @@ -370,10 +370,10 @@ void stdCheckFormatExceptionMessage_should_return_formatted_message_with_Private compasICDHeader.setHeaderId("ID-1"); compasICDHeader.setHeaderVersion("VER-1"); compasICDHeader.setICDSystemVersionUUID("UUID-1"); - TPrivate tPrivate = PrivateService.createPrivate(compasICDHeader); + TPrivate tPrivate = PrivateUtils.createPrivate(compasICDHeader); //When - String message = PrivateService.stdCheckFormatExceptionMessage(tPrivate); + String message = PrivateUtils.stdCheckFormatExceptionMessage(tPrivate); //Then assertThat(message).isEqualTo("headerId = ID-1 headerVersion = VER-1 headerRevision = null and ICDSystemVersionUUID = UUID-1"); @@ -393,9 +393,9 @@ void createMapIEDNameAndPrivate_should_return_map_of_three_items() { compasICDHeader2.setIEDName("IED-2"); TCompasICDHeader compasICDHeader3 = new TCompasICDHeader(); compasICDHeader3.setIEDName("IED-3"); - TPrivate tPrivate1 = PrivateService.createPrivate(compasICDHeader1); - TPrivate tPrivate2 = PrivateService.createPrivate(compasICDHeader2); - TPrivate tPrivate3 = PrivateService.createPrivate(compasICDHeader3); + TPrivate tPrivate1 = PrivateUtils.createPrivate(compasICDHeader1); + TPrivate tPrivate2 = PrivateUtils.createPrivate(compasICDHeader2); + TPrivate tPrivate3 = PrivateUtils.createPrivate(compasICDHeader3); tlNode1.getPrivate().add(tPrivate1); tlNode2.getPrivate().add(tPrivate2); tlNode3.getPrivate().add(tPrivate3); @@ -410,7 +410,7 @@ void createMapIEDNameAndPrivate_should_return_map_of_three_items() { scl.getSubstation().add(tSubstation); //When - Stream tPrivateStream = PrivateService.streamIcdHeaders(scl); + Stream tPrivateStream = PrivateUtils.streamIcdHeaders(scl); //Then assertThat(tPrivateStream.toList()) @@ -426,7 +426,7 @@ void createMapIEDNameAndPrivate_should_return_empty_map_when_no_compasicdheader_ TLNode tlNode1 = new TLNode(); TCompasBay compasBay = new TCompasBay(); compasBay.setUUID("UUID"); - TPrivate tPrivate1 = PrivateService.createPrivate(compasBay); + TPrivate tPrivate1 = PrivateUtils.createPrivate(compasBay); tlNode1.getPrivate().add(tPrivate1); TFunction tFunction = new TFunction(); tFunction.getLNode().add(tlNode1); @@ -439,7 +439,7 @@ void createMapIEDNameAndPrivate_should_return_empty_map_when_no_compasicdheader_ scl.getSubstation().add(tSubstation); //When - Stream tPrivateStream = PrivateService.streamIcdHeaders(scl); + Stream tPrivateStream = PrivateUtils.streamIcdHeaders(scl); //Then assertThat(tPrivateStream.toList()).isEmpty(); @@ -453,11 +453,11 @@ void comparePrivateCompasICDHeaders_should_return_true_equality_not_check_for_IE compasICDHeader1.setBayLabel("BAY-1"); compasICDHeader1.setIEDSubstationinstance(BigInteger.ONE); TCompasICDHeader compasICDHeader2 = new TCompasICDHeader(); - TPrivate tPrivate1 = PrivateService.createPrivate(compasICDHeader1); - TPrivate tPrivate2 = PrivateService.createPrivate(compasICDHeader2); + TPrivate tPrivate1 = PrivateUtils.createPrivate(compasICDHeader1); + TPrivate tPrivate2 = PrivateUtils.createPrivate(compasICDHeader2); // When - boolean result = PrivateService.comparePrivateCompasICDHeaders(tPrivate1,tPrivate2); + boolean result = PrivateUtils.comparePrivateCompasICDHeaders(tPrivate1,tPrivate2); // Then assertThat(result).isTrue(); } @@ -472,11 +472,11 @@ void comparePrivateCompasICDHeaders_should_return_false_equality_not_check_for_I compasICDHeader1.setICDSystemVersionUUID("UUID-1"); TCompasICDHeader compasICDHeader2 = new TCompasICDHeader(); compasICDHeader2.setICDSystemVersionUUID("UUID-2"); - TPrivate tPrivate1 = PrivateService.createPrivate(compasICDHeader1); - TPrivate tPrivate2 = PrivateService.createPrivate(compasICDHeader2); + TPrivate tPrivate1 = PrivateUtils.createPrivate(compasICDHeader1); + TPrivate tPrivate2 = PrivateUtils.createPrivate(compasICDHeader2); // When - boolean result = PrivateService.comparePrivateCompasICDHeaders(tPrivate1,tPrivate2); + boolean result = PrivateUtils.comparePrivateCompasICDHeaders(tPrivate1,tPrivate2); // Then assertThat(result).isFalse(); } @@ -491,11 +491,11 @@ void comparePrivateCompasICDHeaders_should_return_true() { compasICDHeader1.setICDSystemVersionUUID("UUID-1"); TCompasICDHeader compasICDHeader2 = new TCompasICDHeader(); compasICDHeader2.setICDSystemVersionUUID("UUID-1"); - TPrivate tPrivate1 = PrivateService.createPrivate(compasICDHeader1); - TPrivate tPrivate2 = PrivateService.createPrivate(compasICDHeader2); + TPrivate tPrivate1 = PrivateUtils.createPrivate(compasICDHeader1); + TPrivate tPrivate2 = PrivateUtils.createPrivate(compasICDHeader2); // When - boolean result = PrivateService.comparePrivateCompasICDHeaders(tPrivate1,tPrivate2); + boolean result = PrivateUtils.comparePrivateCompasICDHeaders(tPrivate1,tPrivate2); // Then assertThat(result).isTrue(); } @@ -510,13 +510,13 @@ void copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate() { lNodeCompasICDHeader.setIEDName("IED-1"); lNodeCompasICDHeader.setBayLabel("BAY-1"); lNodeCompasICDHeader.setIEDSubstationinstance(BigInteger.ONE); - TPrivate stdTPrivate = PrivateService.createPrivate(stdCompasICDHeader); + TPrivate stdTPrivate = PrivateUtils.createPrivate(stdCompasICDHeader); // When - PrivateService.copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(stdTPrivate, lNodeCompasICDHeader); + PrivateUtils.copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(stdTPrivate, lNodeCompasICDHeader); // Then - TCompasICDHeader result = PrivateService.extractCompasICDHeader(stdTPrivate).get(); + TCompasICDHeader result = PrivateUtils.extractCompasICDHeader(stdTPrivate).get(); assertThat(result).extracting(TCompasICDHeader::getICDSystemVersionUUID, TCompasICDHeader::getIEDName, TCompasICDHeader::getIEDSubstationinstance, TCompasICDHeader::getBayLabel) .containsExactlyInAnyOrder("UUID-2", "IED-1", BigInteger.ONE, "BAY-1"); @@ -528,7 +528,7 @@ void getCompasICDHeaders_should_return_ICDHeaders() { TIED tied = createTIED(); //When - TCompasICDHeader tCompasICDHeader = PrivateService.extractCompasPrivate(tied, TCompasICDHeader.class).orElseThrow(); + TCompasICDHeader tCompasICDHeader = PrivateUtils.extractCompasPrivate(tied, TCompasICDHeader.class).orElseThrow(); //Then assertThat(tCompasICDHeader) @@ -579,7 +579,7 @@ void createPrivate_compas_Topo_should_succeed(){ TCompasTopo tCompasTopo2 = new TCompasTopo(); List compasTopos = List.of(tCompasTopo1, tCompasTopo2); // When - TPrivate result = PrivateService.createPrivate(compasTopos); + TPrivate result = PrivateUtils.createPrivate(compasTopos); // Then assertThat(result.getContent()) .map(JAXBElement.class::cast)