From 09c600fb9a93a87aeda6321b7ba060543bcc68e7 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Wed, 20 Apr 2022 09:28:35 +0200 Subject: [PATCH 01/23] [#65] : correcting history for automation service Signed-off-by: Aliou DIAITE --- .../compas/sct/app/SclAutomationService.java | 4 ++-- .../SclAutomationServiceTest.java | 19 ------------------- 2 files changed, 2 insertions(+), 21 deletions(-) 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 7751c3b7c..260e8437d 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 @@ -23,8 +23,8 @@ public static SclRootAdapter createSCD(@NonNull SCL ssd, @NonNull HeaderDTO head SclRootAdapter scdAdapter = SclService.initScl(Optional.ofNullable(headerDTO.getId()), headerDTO.getVersion(),headerDTO.getRevision()); if(!headerDTO.getHistoryItems().isEmpty()) { - headerDTO.getHistoryItems().forEach(hItem -> - SclService.addHistoryItem(scdAdapter.getCurrentElem(), hItem.getWho(), hItem.getWhat(), hItem.getWhy())); + HeaderDTO.HistoryItem hItem = headerDTO.getHistoryItems().get(0); + SclService.addHistoryItem(scdAdapter.getCurrentElem(), hItem.getWho(), hItem.getWhat(), hItem.getWhy()); } SclService.addSubstation(scdAdapter.getCurrentElem(), ssd); return scdAdapter; 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 4732a918a..4ddfddfa2 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 @@ -12,8 +12,6 @@ import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; -import java.util.Arrays; - import static org.junit.jupiter.api.Assertions.*; class SclAutomationServiceTest { @@ -50,23 +48,6 @@ void createSCD_With_HItem() throws Exception { assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size()); } - @Test - void createSCD_With_HItems() throws Exception { - 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"); - SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO); - assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); - assertEquals(2 ,expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); - } - @Test void createSCD_SSD_Without_Substation() throws Exception { From aaf293499fc6063622207767c258523101d7b48d Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Thu, 21 Apr 2022 09:24:27 +0200 Subject: [PATCH 02/23] [#65 ==> 95] : correcting history for automation service: add test Signed-off-by: Aliou DIAITE --- .../SclAutomationServiceTest.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) 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 4ddfddfa2..f44119d7a 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 @@ -12,6 +12,8 @@ import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import java.util.Arrays; + import static org.junit.jupiter.api.Assertions.*; class SclAutomationServiceTest { @@ -48,8 +50,25 @@ void createSCD_With_HItem() throws Exception { assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size()); } - @Test + void createSCD_With_HItems() throws Exception { + 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"); + SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO); + assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); + assertEquals(1, expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); + assertEquals("what", expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().get(0).getWhat()); + } + + @Test void createSCD_SSD_Without_Substation() throws Exception { SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml"); assertThrows(ScdException.class, From 5de033b77423cf781c53ed3763907af916314b03 Mon Sep 17 00:00:00 2001 From: SaintierFr <99645240+SaintierFr@users.noreply.github.com> Date: Fri, 22 Apr 2022 11:11:32 +0200 Subject: [PATCH 03/23] =?UTF-8?q?Update=20SCL=20communication=20import=20m?= =?UTF-8?q?ethod=20to=20allow=20the=20import=20of=20the=20att=E2=80=A6=20(?= =?UTF-8?q?#91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update SCL communication import method to allow the import of the attributes Address et PhysConn if present. Signed-off-by: SAINTIER FRANCOIS --- sct-commons/pom.xml | 8 +- .../compas/sct/commons/scl/SclService.java | 112 +++++++----- .../commons/scl/com/CommunicationAdapter.java | 11 +- .../commons/scl/com/ConnectedAPAdapter.java | 19 ++ .../sct/commons/scl/SclServiceTest.java | 173 +++++++++++------- .../scl/com/ConnectedAPAdapterTest.java | 69 +++++-- .../ied_with_filled_communication.xml | 111 +++++++++++ 7 files changed, 372 insertions(+), 131 deletions(-) create mode 100644 sct-commons/src/test/resources/scl-srv-import-ieds/ied_with_filled_communication.xml diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index 19512bad9..72a428b47 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -13,7 +13,6 @@ local-SNAPSHOT - org.lfenergy.compas sct-commons local-SNAPSHOT SCT-COMMONS @@ -21,6 +20,7 @@ ${basedir}/${aggregate.report.dir} + 3.22.0 @@ -105,6 +105,12 @@ 2.3.1 compile + + org.assertj + assertj-core + ${assertJ.version} + test + 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 index 16fec6109..0749d29fd 100644 --- 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 @@ -12,6 +12,8 @@ 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; @@ -32,19 +34,22 @@ public class SclService { public static final String UNKNOWN_LDEVICE_S_IN_IED_S = "Unknown LDevice (%s) in IED (%s)"; public 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"); } + private SclService() { + throw new IllegalStateException("SclService class"); + } public static SclRootAdapter initScl(Optional hId, String hVersion, String hRevision) throws ScdException { UUID headerId = hId.orElseGet(UUID::randomUUID); return new SclRootAdapter(headerId.toString(), hVersion, hRevision); } - public static SclRootAdapter addHistoryItem(SCL scd, String who, String what, String why){ + public static SclRootAdapter addHistoryItem(SCL scd, String who, String what, String why) { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); HeaderAdapter headerAdapter = sclRootAdapter.getHeaderAdapter(); - headerAdapter.addHistoryItem(who,what,why); + headerAdapter.addHistoryItem(who, what, why); return sclRootAdapter; } + public static SclRootAdapter updateHeader(@NonNull SCL scd, @NonNull HeaderDTO headerDTO) { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); @@ -53,17 +58,17 @@ public static SclRootAdapter updateHeader(@NonNull SCL scd, @NonNull HeaderDTO h boolean hUpdated = false; String hVersion = headerDTO.getVersion(); String hRevision = headerDTO.getRevision(); - if(hVersion != null && !hVersion.equals(headerAdapter.getHeaderVersion())){ + if (hVersion != null && !hVersion.equals(headerAdapter.getHeaderVersion())) { headerAdapter.updateVersion(hVersion); hUpdated = true; } - if(hRevision != null && !hRevision.equals(headerAdapter.getHeaderRevision())){ + if (hRevision != null && !hRevision.equals(headerAdapter.getHeaderRevision())) { headerAdapter.updateRevision(hRevision); hUpdated = true; } - if(hUpdated && !headerDTO.getHistoryItems().isEmpty()){ + if (hUpdated && !headerDTO.getHistoryItems().isEmpty()) { headerAdapter.addHistoryItem( headerDTO.getHistoryItems().get(0).getWho(), headerDTO.getHistoryItems().get(0).getWhat(), @@ -74,24 +79,32 @@ public static SclRootAdapter updateHeader(@NonNull SCL scd, @NonNull HeaderDTO h return sclRootAdapter; } - public static IEDAdapter addIED(SCL scd, String iedName, SCL icd) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - return sclRootAdapter.addIED(icd,iedName); + return sclRootAdapter.addIED(icd, iedName); } - public static Optional addSubnetworks(SCL scd, Set subNetworks) throws ScdException { + public static Optional addSubnetworks(SCL scd, Set subNetworks, Optional icd) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - CommunicationAdapter communicationAdapter = null; - if(!subNetworks.isEmpty()) { + 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()) { - communicationAdapter.addSubnetwork(snName, snType, - accessPoint.getIedName(), accessPoint.getApName()); + String iedName = accessPoint.getIedName(); + String apName = accessPoint.getApName(); + communicationAdapter.addSubnetwork(snName, snType, iedName, apName); + + Optional subNetworkAdapter = communicationAdapter.getSubnetworkByName(snName); + if (subNetworkAdapter.isPresent()) { + ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.get() + .getConnectedAPAdapter(iedName, apName); + connectedAPAdapter.copyAddressAndPhysConnFromIcd(icd); + } + } } return Optional.of(communicationAdapter); @@ -121,7 +134,7 @@ public static List getExtRefInfo(SCL scd, String iedName, String ldI public static List getExtRefBinders(SCL scd, String iedName, String ldInst, - String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException { + String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) @@ -141,14 +154,14 @@ public static List getExtRefBinders(SCL scd, String iedName, // find potential binders for the signalInfo List potentialBinders = new ArrayList<>(); - for(IEDAdapter iedA : sclRootAdapter.getIEDAdapters()){ + for (IEDAdapter iedA : sclRootAdapter.getIEDAdapters()) { potentialBinders.addAll(iedA.getExtRefBinders(signalInfo)); } return potentialBinders; } public static void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws ScdException { - if(extRefInfo.getBindingInfo() == null || extRefInfo.getSignalInfo() == null){ + if (extRefInfo.getBindingInfo() == null || extRefInfo.getSignalInfo() == null) { throw new ScdException("ExtRef Signal and/or Binding information are missing"); } String iedName = extRefInfo.getHolderIEDName(); @@ -157,11 +170,11 @@ public static void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws Sc IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) .orElseThrow( - () -> new ScdException( - String.format( - UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName - ) - ) + () -> new ScdException( + String.format( + UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName + ) + ) ); AbstractLNAdapter abstractLNAdapter = AbstractLNAdapter.builder() @@ -179,16 +192,16 @@ public static List> getExtRefSourceInfo(SCL scd, ExtRefInfo extR ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); - if(!signalInfo.isValid()){ + if (!signalInfo.isValid()) { throw new ScdException("Invalid or missing attributes in ExtRef signal info"); } ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo(); - if(!bindingInfo.isValid()){ + if (!bindingInfo.isValid()) { throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); } String iedName = extRefInfo.getHolderIEDName(); - if(bindingInfo.getIedName().equals(iedName)){ + if (bindingInfo.getIedName().equals(iedName)) { throw new ScdException("Internal binding can't have control block"); } @@ -234,18 +247,18 @@ public static TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws String prefix = extRefInfo.getHolderLnPrefix(); ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); - if(signalInfo == null || !signalInfo.isValid()){ + 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()){ + if (bindingInfo == null || !bindingInfo.isValid()) { throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); } - if(bindingInfo.getIedName().equals(iedName)){ + if (bindingInfo.getIedName().equals(iedName)) { throw new ScdException("Internal binding can't have control block"); } ExtRefSourceInfo sourceInfo = extRefInfo.getSourceInfo(); - if(sourceInfo == null || !sourceInfo.isValid()){ + if (sourceInfo == null || !sourceInfo.isValid()) { throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); } @@ -265,9 +278,9 @@ public static TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws } public static Set getDAI(SCL scd, String iedName, String ldInst, - ResumedDataTemplate rDtt, boolean updatable) throws ScdException { + ResumedDataTemplate rDtt, boolean updatable) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iedAdapter = new IEDAdapter(sclRootAdapter,iedName); + IEDAdapter iedAdapter = new IEDAdapter(sclRootAdapter, iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) .orElseThrow( () -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName)) @@ -284,9 +297,9 @@ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedData DataTypeTemplateAdapter dttAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); LNodeTypeAdapter lNodeTypeAdapter = dttAdapter.getLNodeTypeAdapterById(rDtt.getLnType()) .orElseThrow(() -> new ScdException("Unknown LNodeType : " + rDtt.getLnType())); - lNodeTypeAdapter.check(rDtt.getDoName(),rDtt.getDaName()); + lNodeTypeAdapter.check(rDtt.getDoName(), rDtt.getDaName()); - if(TPredefinedBasicTypeEnum.OBJ_REF == rDtt.getBType()){ + if (TPredefinedBasicTypeEnum.OBJ_REF == rDtt.getBType()) { Long sGroup = rDtt.getDaName().getDaiValues().keySet().stream().findFirst().orElse(-1L); String val = sGroup < 0 ? null : rDtt.getDaName().getDaiValues().get(sGroup); sclRootAdapter.checkObjRef(val); @@ -306,8 +319,8 @@ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedData .withLnPrefix(rDtt.getPrefix()) .build(); - if(TPredefinedCDCEnum.ING == rDtt.getCdc() || TPredefinedCDCEnum.ASG == rDtt.getCdc() ){ - DAITracker daiTracker = new DAITracker(lnAdapter,rDtt.getDoName(),rDtt.getDaName()); + if (TPredefinedCDCEnum.ING == rDtt.getCdc() || TPredefinedCDCEnum.ASG == rDtt.getCdc()) { + DAITracker daiTracker = new DAITracker(lnAdapter, rDtt.getDoName(), rDtt.getDaName()); daiTracker.validateBoundedDAI(); } lnAdapter.updateDAI(rDtt); @@ -316,44 +329,45 @@ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedData public static Set> getEnumTypeElements(SCL scd, String idEnum) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - DataTypeTemplateAdapter dataTypeTemplateAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); + DataTypeTemplateAdapter dataTypeTemplateAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); EnumTypeAdapter enumTypeAdapter = dataTypeTemplateAdapter.getEnumTypeAdapterById(idEnum) - .orElseThrow(() -> new ScdException("Unknown EnumType Id: " + idEnum)); + .orElseThrow(() -> new ScdException("Unknown EnumType Id: " + idEnum)); return enumTypeAdapter.getCurrentElem().getEnumVal().stream() - .map(tEnumVal -> Pair.of(tEnumVal.getOrd(),tEnumVal.getValue())) + .map(tEnumVal -> Pair.of(tEnumVal.getOrd(), tEnumVal.getValue())) .collect(Collectors.toSet()); } public static SclRootAdapter addSubstation(@NonNull SCL scd, @NonNull SCL ssd) throws ScdException { SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); SclRootAdapter ssdRootAdapter = new SclRootAdapter(ssd); - if(scdRootAdapter.getCurrentElem().getSubstation().size() > 1 - || ssdRootAdapter.currentElem.getSubstation().size() != 1) { + if (scdRootAdapter.getCurrentElem().getSubstation().size() > 1 + || ssdRootAdapter.currentElem.getSubstation().size() != 1) { throw new ScdException("SCD file must have one or zero Substation and " + "SCD file must have one Substation. The files are rejected."); } TSubstation ssdTSubstation = ssdRootAdapter.currentElem.getSubstation().get(0); - if(scdRootAdapter.getCurrentElem().getSubstation().isEmpty()) { + if (scdRootAdapter.getCurrentElem().getSubstation().isEmpty()) { scdRootAdapter.getCurrentElem().getSubstation().add(ssdTSubstation); return scdRootAdapter; } else { TSubstation scdTSubstation = scdRootAdapter.currentElem.getSubstation().get(0); - if(scdTSubstation.getName().equalsIgnoreCase(ssdTSubstation.getName())) { + if (scdTSubstation.getName().equalsIgnoreCase(ssdTSubstation.getName())) { SubstationAdapter scdSubstationAdapter = scdRootAdapter.getSubstationAdapter(scdTSubstation.getName()); - for(TVoltageLevel tvl : ssdTSubstation.getVoltageLevel()){ + for (TVoltageLevel tvl : ssdTSubstation.getVoltageLevel()) { updateVoltageLevel(scdSubstationAdapter, tvl); } - } else throw new ScdException("SCD file must have only one Substation and the Substation name from SSD file is" + - " different from the one in SCD file. The files are rejected."); + } else + throw new ScdException("SCD file must have only one Substation and the Substation name from SSD file is" + + " different from the one in SCD file. The files are rejected."); } return scdRootAdapter; } private static void updateVoltageLevel(@NonNull SubstationAdapter scdSubstationAdapter, TVoltageLevel vl) throws ScdException { - if(scdSubstationAdapter.getVoltageLevelAdapter(vl.getName()).isPresent()) { + if (scdSubstationAdapter.getVoltageLevelAdapter(vl.getName()).isPresent()) { VoltageLevelAdapter scdVoltageLevelAdapter = scdSubstationAdapter.getVoltageLevelAdapter(vl.getName()) .orElseThrow(() -> new ScdException("Unable to create VoltageLevelAdapter")); - for (TBay tbay: vl.getBay()) { + for (TBay tbay : vl.getBay()) { updateBay(scdVoltageLevelAdapter, tbay); } } else { @@ -362,9 +376,9 @@ private static void updateVoltageLevel(@NonNull SubstationAdapter scdSubstationA } private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapter, TBay tBay) { - if(scdVoltageLevelAdapter.getBayAdapter(tBay.getName()).isPresent()){ - scdVoltageLevelAdapter.getCurrentElem().getBay() - .removeIf(t -> t.getName().equalsIgnoreCase(tBay.getName())); + if (scdVoltageLevelAdapter.getBayAdapter(tBay.getName()).isPresent()) { + scdVoltageLevelAdapter.getCurrentElem().getBay() + .removeIf(t -> t.getName().equalsIgnoreCase(tBay.getName())); scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); } else { scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java index 917ea2853..37d54dd67 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java @@ -1,4 +1,3 @@ - // SPDX-FileCopyrightText: 2021 RTE FRANCE // // SPDX-License-Identifier: Apache-2.0 @@ -43,16 +42,16 @@ public SubNetworkAdapter addSubnetwork(String snName, String snType, String iedName, String apName) throws ScdException { IEDAdapter iedAdapter = parentAdapter.getIEDAdapterByName(iedName); - if(!iedAdapter.findAccessPointByName(apName)){ + if (!iedAdapter.findAccessPointByName(apName)) { throw new ScdException("Unknown AccessPoint :" + apName + " in IED :" + iedName); } Optional opSubNetworkAdapter = getSubnetworkByName(snName); - if(!opSubNetworkAdapter.isPresent()){ // create new subnetwork + if (opSubNetworkAdapter.isEmpty()) { // create new subnetwork TSubNetwork subNetwork = new TSubNetwork(); subNetwork.setName(snName); subNetwork.setType(snType); currentElem.getSubNetwork().add(subNetwork); - opSubNetworkAdapter = Optional.of(new SubNetworkAdapter(this,subNetwork)); + opSubNetworkAdapter = Optional.of(new SubNetworkAdapter(this, subNetwork)); } opSubNetworkAdapter.get().addConnectedAP(iedName,apName); @@ -65,13 +64,13 @@ public Optional getSubnetworkByName(String snName) { .stream() .filter(tSubNetwork -> tSubNetwork.getName().equals(snName)) .findFirst() - .map(tSubNetwork -> new SubNetworkAdapter(this,tSubNetwork)); + .map(tSubNetwork -> new SubNetworkAdapter(this, tSubNetwork)); } public List getSubNetworkAdapters() { return currentElem.getSubNetwork() .stream() - .map(tSubNetwork -> new SubNetworkAdapter(this,tSubNetwork)) + .map(tSubNetwork -> new SubNetworkAdapter(this, tSubNetwork)) .collect(Collectors.toList()); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java index b0fd21141..280b15fba 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java @@ -4,10 +4,13 @@ package org.lfenergy.compas.sct.commons.scl.com; +import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TConnectedAP; import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import java.util.Optional; + public class ConnectedAPAdapter extends SclElementAdapter { public ConnectedAPAdapter(SubNetworkAdapter parentAdapter, TConnectedAP currentElem) { @@ -31,4 +34,20 @@ public String getIedName() { public String getApName() { return currentElem.getApName(); } + + public void copyAddressAndPhysConnFromIcd(Optional icd) { + if (icd.isPresent() && icd.get().getCommunication() != null) { + icd.stream() + .map(SCL::getCommunication) + .findFirst() + .flatMap(com -> com.getSubNetwork().stream() + .flatMap(subNet -> subNet.getConnectedAP().stream() + .filter(connAP -> connAP.getApName().equals(currentElem.getApName()))) + .findFirst()).ifPresent(connectedAP -> { + currentElem.setAddress(connectedAP.getAddress()); + currentElem.getPhysConn().addAll(connectedAP.getPhysConn()); + }); + + } + } } 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/scl/SclServiceTest.java index e817b30a3..b02de9717 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/scl/SclServiceTest.java @@ -16,43 +16,41 @@ import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; class SclServiceTest { @Test void testAddHistoryItem() throws ScdException { - SclRootAdapter sclRootAdapter= new SclRootAdapter("hId",SclRootAdapter.VERSION,SclRootAdapter.REVISION); + SclRootAdapter sclRootAdapter = new SclRootAdapter("hId", SclRootAdapter.VERSION, SclRootAdapter.REVISION); SCL scd = sclRootAdapter.getCurrentElem(); - SclService.addHistoryItem(scd,"who","what","why"); + SclService.addHistoryItem(scd, "who", "what", "why"); assertNotNull(scd.getHeader()); THeader.History history = scd.getHeader().getHistory(); assertNotNull(history); - assertEquals(1,history.getHitem().size()); + assertEquals(1, history.getHitem().size()); THitem tHitem = history.getHitem().get(0); - assertEquals("who",tHitem.getWho()); - assertEquals("what",tHitem.getWhat()); - assertEquals("why",tHitem.getWhy()); - assertEquals(SclRootAdapter.REVISION,tHitem.getRevision()); - assertEquals(SclRootAdapter.VERSION,tHitem.getVersion()); + assertEquals("who", tHitem.getWho()); + assertEquals("what", tHitem.getWhat()); + assertEquals("why", tHitem.getWhy()); + assertEquals(SclRootAdapter.REVISION, tHitem.getRevision()); + assertEquals(SclRootAdapter.VERSION, tHitem.getVersion()); } @Test void testAddIED() throws Exception { - SclRootAdapter sclRootAdapter= new SclRootAdapter("hId",SclRootAdapter.VERSION,SclRootAdapter.REVISION); + 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"); - IEDAdapter iedAdapter = assertDoesNotThrow(() -> SclService.addIED(scd,"IED_NAME1",icd)); + IEDAdapter iedAdapter = assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd)); assertEquals("IED_NAME1", iedAdapter.getName()); assertNotNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); @@ -77,11 +75,60 @@ void testAddSubnetworks() throws Exception { connectedApDTO.setIedName("IED_NAME1"); subNetworkDTO.addConnectedAP(connectedApDTO); - assertDoesNotThrow(() -> SclService.addSubnetworks(scd, Set.of(subNetworkDTO)).get()); + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, Set.of(subNetworkDTO), Optional.of(icd)).get()); MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); System.out.println(marshallerWrapper.marshall(scd)); } + @Test + void testAddSubnetworksWithoutCommunicationTagInIcd() throws Exception { + 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)); + + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, new HashSet<>(), Optional.of(icd))); + MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); + String marshalledScd = marshallerWrapper.marshall(scd); + assertThat(marshalledScd).doesNotContain(" SclService.addIED(scd, "IED_NAME1", icd)); + + Set subNetworkDTOSet = new HashSet<>(SclService.getSubnetwork(icd)); + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, subNetworkDTOSet, Optional.of(icd)).get()); + + MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); + String marshalledScd = marshallerWrapper.marshall(scd); + assertThat(marshalledScd).contains("
", "PhysConn"); + } + + @Test + void testAddSubnetworksWithoutImportingIcdAddressAndPhysConn() throws Exception { + 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)); + + Set subNetworkDTOSet = new HashSet<>(SclService.getSubnetwork(icd)); + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, subNetworkDTOSet, Optional.empty()).get()); + + MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); + String marshalledScd = marshallerWrapper.marshall(scd); + assertThat(marshalledScd).doesNotContain("
", "PhysConn"); + } + @Test void testGetSubnetwork() throws Exception { @@ -100,26 +147,26 @@ void testGetSubnetwork() throws Exception { connectedApDTO.setIedName("IED_NAME1"); subNetworkDTO.addConnectedAP(connectedApDTO); - assertDoesNotThrow(() -> SclService.addSubnetworks(scd, Set.of(subNetworkDTO)).get()); + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, Set.of(subNetworkDTO), Optional.of(icd)).get()); - List subNetworkDTOS = assertDoesNotThrow(()-> SclService.getSubnetwork(scd)); - assertEquals(1,subNetworkDTOS.size()); + List subNetworkDTOS = assertDoesNotThrow(() -> SclService.getSubnetwork(scd)); + assertEquals(1, subNetworkDTOS.size()); } @Test void testGetExtRefInfo() throws Exception { - SclRootAdapter sclRootAdapter= new SclRootAdapter("hId",SclRootAdapter.VERSION,SclRootAdapter.REVISION); + 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()); + 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()); + assertEquals("IED_NAME1", extRefInfos.get(0).getHolderIEDName()); - assertThrows(ScdException.class, () -> SclService.getExtRefInfo(scd,"IED_NAME1","UNKNOWN_LD")); + assertThrows(ScdException.class, () -> SclService.getExtRefInfo(scd, "IED_NAME1", "UNKNOWN_LD")); } @Test @@ -127,36 +174,36 @@ void testGetExtRefBinders() throws Exception { 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" + "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" ); List potentialBinders = assertDoesNotThrow( () -> SclService.getExtRefBinders( - scd,"IED_NAME1","LD_INST11","LLN0","","",signalInfo + scd, "IED_NAME1", "LD_INST11", "LLN0", "", "", signalInfo ) ); assertThrows( ScdException.class, () -> SclService.getExtRefBinders( - scd,"IED_NAME1","UNKNOWN_LD","LLN0","","",signalInfo + scd, "IED_NAME1", "UNKNOWN_LD", "LLN0", "", "", signalInfo ) ); } @Test void testUpdateExtRefBinders() throws Exception { - SclRootAdapter sclRootAdapter= new SclRootAdapter("hId",SclRootAdapter.VERSION,SclRootAdapter.REVISION); + 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)); + 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" + "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" ); signalInfo.setPServT(null); signalInfo.setPLN(null); @@ -182,13 +229,13 @@ void testUpdateExtRefBinders() throws Exception { lNodeDTO.getExtRefs().add(extRefInfo); assertDoesNotThrow( - () -> SclService.updateExtRefBinders(scd,extRefInfo) + () -> SclService.updateExtRefBinders(scd, extRefInfo) ); extRefInfo.setHolderLDInst("UNKNOWN_LD"); assertThrows( ScdException.class, - () -> SclService.updateExtRefBinders( scd,extRefInfo) + () -> SclService.updateExtRefBinders(scd, extRefInfo) ); } @@ -211,10 +258,10 @@ void testGetExtRefSourceInfo() throws Exception { extRefInfo.setHolderLDInst(ldInst); extRefInfo.setHolderLnClass(lnClass); - var controlBlocks = SclService.getExtRefSourceInfo(scd,extRefInfo); - assertEquals(2,controlBlocks.size()); + var controlBlocks = SclService.getExtRefSourceInfo(scd, extRefInfo); + assertEquals(2, controlBlocks.size()); controlBlocks.forEach(controlBlock -> assertTrue( - controlBlock.getName().equals("goose1") || controlBlock.getName().equals("smv1") + controlBlock.getName().equals("goose1") || controlBlock.getName().equals("smv1") ) ); } @@ -227,21 +274,21 @@ void testUpdateExtRefSource() throws Exception { extRefInfo.setHolderLDInst("LD_INST21"); extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // signal = null + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // signal = null extRefInfo.setSignalInfo(new ExtRefSignalInfo()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // signal invalid + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // signal invalid extRefInfo.getSignalInfo().setIntAddr("INT_ADDR21"); extRefInfo.getSignalInfo().setPDA("da21.bda211.bda212.bda213"); extRefInfo.getSignalInfo().setPDO("Do21.sdo21"); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // binding = null + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // binding = null extRefInfo.setBindingInfo(new ExtRefBindingInfo()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // binding invalid + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // binding invalid extRefInfo.getBindingInfo().setIedName("IED_NAME2"); // internal binding extRefInfo.getBindingInfo().setLdInst("LD_INST12"); extRefInfo.getBindingInfo().setLnClass(TLLN0Enum.LLN_0.value()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // CB not allowed + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // CB not allowed extRefInfo.getBindingInfo().setIedName("IED_NAME1"); @@ -249,12 +296,12 @@ void testUpdateExtRefSource() throws Exception { extRefInfo.getSourceInfo().setSrcLDInst(extRefInfo.getBindingInfo().getLdInst()); extRefInfo.getSourceInfo().setSrcLNClass(extRefInfo.getBindingInfo().getLnClass()); extRefInfo.getSourceInfo().setSrcCBName("goose1"); - TExtRef extRef = assertDoesNotThrow( () -> SclService.updateExtRefSource(scd,extRefInfo)); - assertEquals(extRefInfo.getSourceInfo().getSrcCBName(),extRef.getSrcCBName()); + TExtRef extRef = assertDoesNotThrow(() -> SclService.updateExtRefSource(scd, extRefInfo)); + assertEquals(extRefInfo.getSourceInfo().getSrcCBName(), extRef.getSrcCBName()); } - private ExtRefSignalInfo createSignalInfo(String pDO, String pDA, String intAddr){ + private ExtRefSignalInfo createSignalInfo(String pDO, String pDA, String intAddr) { final String DESC = "DESC"; final String P_LN = TLLN0Enum.LLN_0.value(); @@ -277,32 +324,32 @@ void testGetDAI() throws Exception { Set resumedDataTemplates = assertDoesNotThrow( - ()-> SclService.getDAI( - scd,"IED_NAME1","LD_INST12",new ResumedDataTemplate(),true + () -> SclService.getDAI( + scd, "IED_NAME1", "LD_INST12", new ResumedDataTemplate(), true ) ); - assertEquals(13,resumedDataTemplates.size()); + assertEquals(13, resumedDataTemplates.size()); assertThrows( ScdException.class, - ()-> SclService.getDAI( - scd,"IED_NAME1","UNKNOWNLD",new ResumedDataTemplate(),true + () -> SclService.getDAI( + scd, "IED_NAME1", "UNKNOWNLD", new ResumedDataTemplate(), true ) ); } @Test - void testInitScl(){ + void testInitScl() { assertDoesNotThrow( - () -> SclService.initScl(Optional.empty(), "hVersion","hRevision") + () -> SclService.initScl(Optional.empty(), "hVersion", "hRevision") ); } @Test - void testInitScl_With_hId_shouldNotThrowError(){ + void testInitScl_With_hId_shouldNotThrowError() { UUID hid = UUID.randomUUID(); assertDoesNotThrow( - () -> SclService.initScl(Optional.of(hid),"hVersion","hRevision") + () -> SclService.initScl(Optional.of(hid), "hVersion", "hRevision") ); } @@ -310,12 +357,12 @@ void testInitScl_With_hId_shouldNotThrowError(){ void testUpdateHeader() { SclRootAdapter sclRootAdapter = assertDoesNotThrow( - () -> SclService.initScl(Optional.empty(),"hVersion","hRevision") + () -> SclService.initScl(Optional.empty(), "hVersion", "hRevision") ); UUID hId = UUID.fromString(sclRootAdapter.getHeaderAdapter().getHeaderId()); HeaderDTO headerDTO = DTO.createHeaderDTO(hId); - SclService.updateHeader(sclRootAdapter.getCurrentElem(),headerDTO); - SclService.updateHeader(sclRootAdapter.getCurrentElem(),headerDTO); + SclService.updateHeader(sclRootAdapter.getCurrentElem(), headerDTO); + SclService.updateHeader(sclRootAdapter.getCurrentElem(), headerDTO); } @@ -326,8 +373,8 @@ void testUpdateDAI() throws Exception { SCL scd = SclTestMarshaller.getSCLFromFile("/ied-test-schema-conf/ied_unit_test.xml"); SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - assertThrows(ScdException.class, ()-> SclService.updateDAI( - scd,"IED","LD",rDtt + assertThrows(ScdException.class, () -> SclService.updateDAI( + scd, "IED", "LD", rDtt )); rDtt.setLnType("LNO1"); rDtt.setLnClass(TLLN0Enum.LLN_0.value()); @@ -337,17 +384,17 @@ void testUpdateDAI() throws Exception { TVal tVal = new TVal(); tVal.setValue("newValue"); rDtt.setDaiValues(List.of(tVal)); - assertDoesNotThrow(() -> SclService.updateDAI(scd,"IED_NAME","LD_INS1",rDtt)); + assertDoesNotThrow(() -> SclService.updateDAI(scd, "IED_NAME", "LD_INS1", rDtt)); } @Test void testGetEnumTypeElements() throws Exception { SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - assertThrows(ScdException.class, ()-> SclService.getEnumTypeElements(scd,"unknwnID")); + assertThrows(ScdException.class, () -> SclService.getEnumTypeElements(scd, "unknwnID")); var enumList = assertDoesNotThrow( - ()-> SclService.getEnumTypeElements(scd,"RecCycModKind") + () -> SclService.getEnumTypeElements(scd, "RecCycModKind") ); assertFalse(enumList.isEmpty()); } @@ -359,7 +406,7 @@ void testAddSubstation_Check_SSD_Validity(String ssdFileName) throws Exception { SCL ssd = SclTestMarshaller.getSCLFromFile(ssdFileName); assertThrows(ScdException.class, - () ->SclService.addSubstation(scd, ssd)); + () -> SclService.addSubstation(scd, ssd)); } @Test @@ -380,7 +427,7 @@ void testAddSubstation_SCD_With_Different_Substation_Name() throws Exception { SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); assertThrows(ScdException.class, - () ->SclService.addSubstation(scd, ssd)); + () -> SclService.addSubstation(scd, ssd)); } @Test diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapterTest.java index 1bdc8db25..b71d8790d 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapterTest.java @@ -4,40 +4,48 @@ package org.lfenergy.compas.sct.commons.scl.com; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TConnectedAP; import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.scl2007b4.model.TSubNetwork; import org.lfenergy.compas.sct.commons.dto.DTO; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; + +import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.*; class ConnectedAPAdapterTest { - @Test - void testAmChildElementRef() { - SubNetworkAdapter subNetworkAdapter = new SubNetworkAdapter(null, new TSubNetwork()); + private SubNetworkAdapter subNetworkAdapter; + + @BeforeEach + void setUp() { + subNetworkAdapter = new SubNetworkAdapter(null, new TSubNetwork()); TConnectedAP tConnectedAP = new TConnectedAP(); tConnectedAP.setIedName(DTO.HOLDER_IED_NAME); tConnectedAP.setApName(DTO.AP_NAME); subNetworkAdapter.getCurrentElem().getConnectedAP().add(tConnectedAP); + } + @Test + void testAmChildElementRef() { ConnectedAPAdapter connectedAPAdapter = assertDoesNotThrow( - () ->subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME,DTO.AP_NAME) + () -> subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME, DTO.AP_NAME) ); - assertEquals(DTO.HOLDER_IED_NAME,connectedAPAdapter.getIedName()); - assertEquals(DTO.AP_NAME,connectedAPAdapter.getApName()); + assertEquals(DTO.HOLDER_IED_NAME, connectedAPAdapter.getIedName()); + assertEquals(DTO.AP_NAME, connectedAPAdapter.getApName()); } @Test void addPrivate() throws Exception { - SubNetworkAdapter subNetworkAdapter = new SubNetworkAdapter(null, new TSubNetwork()); - TConnectedAP tConnectedAP = new TConnectedAP(); - tConnectedAP.setIedName(DTO.HOLDER_IED_NAME); - tConnectedAP.setApName(DTO.AP_NAME); - subNetworkAdapter.getCurrentElem().getConnectedAP().add(tConnectedAP); - ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME,DTO.AP_NAME); + ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME, DTO.AP_NAME); TPrivate tPrivate = new TPrivate(); tPrivate.setType("Private Type"); tPrivate.setSource("Private Source"); @@ -45,4 +53,41 @@ void addPrivate() throws Exception { connectedAPAdapter.addPrivate(tPrivate); assertEquals(1, connectedAPAdapter.getCurrentElem().getPrivate().size()); } + + @Test + void testCopyAddressAndPhysConnFromIcd_withFilledCommunication() throws Exception { + // GIVEN + ConnectedAPAdapter connectedAPAdapter = assertDoesNotThrow( + () -> subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME, DTO.AP_NAME) + ); + + SCL icd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_with_filled_communication.xml"); + SclRootAdapter icdRootAdapter = new SclRootAdapter(icd); + Optional opIcd = Optional.of(icdRootAdapter.getCurrentElem()); + + // WHEN + connectedAPAdapter.copyAddressAndPhysConnFromIcd(opIcd); + + // THEN + assertThat(connectedAPAdapter.getCurrentElem().getAddress()).isNotNull(); + assertThat(connectedAPAdapter.getCurrentElem().getPhysConn()).isNotNull(); + assertThat(connectedAPAdapter.getCurrentElem().getGSE()).isEmpty(); + } + + @Test + void testCopyAddressAndPhysConnFromIcd_withEmptyIcd() { + // GIVEN + ConnectedAPAdapter connectedAPAdapter = assertDoesNotThrow( + () -> subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME, DTO.AP_NAME) + ); + Optional opIcd = Optional.empty(); + + // WHEN + connectedAPAdapter.copyAddressAndPhysConnFromIcd(opIcd); + + // THEN + assertThat(connectedAPAdapter.getCurrentElem().getAddress()).isNull(); + assertThat(connectedAPAdapter.getCurrentElem().getPhysConn()).isEmpty(); + assertThat(connectedAPAdapter.getCurrentElem().getGSE()).isEmpty(); + } } \ No newline at end of file diff --git a/sct-commons/src/test/resources/scl-srv-import-ieds/ied_with_filled_communication.xml b/sct-commons/src/test/resources/scl-srv-import-ieds/ied_with_filled_communication.xml new file mode 100644 index 000000000..6639adcf7 --- /dev/null +++ b/sct-commons/src/test/resources/scl-srv-import-ieds/ied_with_filled_communication.xml @@ -0,0 +1,111 @@ + + + + + +
+ + + +
+

1.2.3.4

+
+ +
+

11

+
+
+ +

PL

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + myVal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Completed-diff + + + \ No newline at end of file From 0a9ff1e0296a4927b1e484d073d943560e156ae1 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Fri, 22 Apr 2022 13:25:44 +0200 Subject: [PATCH 04/23] [#66] : WIP Signed-off-by: Aliou DIAITE --- pom.xml | 9 +++++ sct-commons/pom.xml | 6 ++- .../compas/sct/commons/scl/SclService.java | 39 +++++++++++++++++++ .../sct/commons/scl/SclServiceTest.java | 16 ++++++-- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 8b5b10e77..5331fab3b 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,11 @@ scl2007b4 0.2.1 + + org.lfenergy.compas.core + scl-extension + 0.8.0 + ch.qos.logback logback-classic @@ -80,6 +85,10 @@ org.lfenergy.compas.core scl2007b4 + + org.lfenergy.compas.core + scl-extension + ch.qos.logback logback-classic diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index 19512bad9..d8bf3c057 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -132,7 +132,6 @@ unpack - @@ -140,6 +139,11 @@ compas-scl-xsd 0.0.4 + + org.lfenergy.compas.core + scl-extension + 0.8.0 + ${project.build.directory} 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 index 16fec6109..d67153d32 100644 --- 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 @@ -7,6 +7,7 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; +import org.lfenergy.compas.scl.extensions.model.TCompasICDHeader; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.Utils; import org.lfenergy.compas.sct.commons.dto.*; @@ -370,4 +371,42 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); } } + + public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapter, List stds){ + + // List all Private /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader + + Map tPrivateMap = new HashMap<>(); + + scdRootAdapter.getCurrentElem().getSubstation().get(0).getVoltageLevel() + .forEach(tVoltageLevel -> tVoltageLevel.getBay() + .forEach(tBay -> tBay.getFunction() + .forEach(tFunction -> tFunction.getLNode() + .forEach(tlNode -> tlNode.getPrivate() + .forEach(tPrivate -> { + if(tPrivate.getType().equals("COMPAS-ICDHeader")){ + tPrivate.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .forEach(o -> { + TCompasICDHeader tCompasICDHeader = (TCompasICDHeader) o; + tPrivateMap.put(tCompasICDHeader.getIEDName(), tPrivate);}); + } + }) + ) + ) + ) + ); + + //Remove duplicated one with same iedName + //For each Private.ICDSystemVersionUUID and Private.iedName find STD File + //if =! 1 error + //else import /dtt in Scd + // import /ied and give /ied.name = Private.iedName + //if /IED/Private/compas:ICDHeader == /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader (~3param) + //copy 3 param into /IED/Private/compas:ICDHeader ( @BayLabel @iedName @IEDinstance) + //import connectedAP (correspondance from file) + //and rename Communication/Subnetwork/ConnectedAP/@iedName by /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader @iedName + + return scdRootAdapter; + } } 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/scl/SclServiceTest.java index e817b30a3..caeb7fc79 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/scl/SclServiceTest.java @@ -4,6 +4,7 @@ package org.lfenergy.compas.sct.commons.scl; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -16,10 +17,7 @@ import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; import static org.junit.jupiter.api.Assertions.*; @@ -397,4 +395,14 @@ void testAddSubstation_SCD_With_Substation() throws Exception { assertEquals(expectedTSubstation.getName(), tSubstation.getName()); assertEquals(expectedTSubstation.getVoltageLevel().size(), tSubstation.getVoltageLevel().size()); } + + @Test + @Disabled + void importIEDInSCD() throws Exception { + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/scd_with_substation.xml"); + SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + + SclRootAdapter expectedScdAdapter = SclService.importIEDInSCD(scdRootAdapter, new ArrayList<>()); + + } } \ No newline at end of file From 25fdaa640c3b348763a4beb269e35e6dd6ccbe28 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Tue, 26 Apr 2022 16:01:10 +0200 Subject: [PATCH 05/23] [#66] : WIP to be refactored Signed-off-by: Aliou DIAITE --- .../compas/sct/commons/scl/SclService.java | 171 ++++++++++++++++-- .../sct/commons/scl/SclServiceTest.java | 7 +- 2 files changed, 156 insertions(+), 22 deletions(-) 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 index d67153d32..e0c2370b3 100644 --- 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 @@ -23,7 +23,9 @@ import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter; +import org.w3c.dom.Element; +import javax.xml.bind.JAXBElement; import java.util.*; import java.util.stream.Collectors; @@ -32,6 +34,8 @@ public class SclService { public static final String UNKNOWN_LDEVICE_S_IN_IED_S = "Unknown LDevice (%s) in IED (%s)"; public static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info"; + public static final String COMPAS_ICDHEADER = "COMPAS-ICDHeader"; + public static final String ICD_SYSTEM_VERSION_UUID = "ICDSystemVersionUUID"; private SclService(){ throw new IllegalStateException("SclService class"); } @@ -372,9 +376,9 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte } } - public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapter, List stds){ - + public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapter, List stds) throws ScdException { // List all Private /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader + //Remove duplicated one with same iedName Map tPrivateMap = new HashMap<>(); @@ -384,29 +388,160 @@ public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapt .forEach(tFunction -> tFunction.getLNode() .forEach(tlNode -> tlNode.getPrivate() .forEach(tPrivate -> { - if(tPrivate.getType().equals("COMPAS-ICDHeader")){ - tPrivate.getContent().stream() - .filter(o -> !o.toString().trim().isBlank()) - .forEach(o -> { - TCompasICDHeader tCompasICDHeader = (TCompasICDHeader) o; - tPrivateMap.put(tCompasICDHeader.getIEDName(), tPrivate);}); - } + if (tPrivate.getType().equals(COMPAS_ICDHEADER)) { + tPrivate.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .forEach(o -> tPrivateMap.put((((Element) o).getAttribute("IEDName")), tPrivate)); + } }) ) ) ) ); - //Remove duplicated one with same iedName //For each Private.ICDSystemVersionUUID and Private.iedName find STD File - //if =! 1 error - //else import /dtt in Scd - // import /ied and give /ied.name = Private.iedName - //if /IED/Private/compas:ICDHeader == /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader (~3param) - //copy 3 param into /IED/Private/compas:ICDHeader ( @BayLabel @iedName @IEDinstance) - //import connectedAP (correspondance from file) - //and rename Communication/Subnetwork/ConnectedAP/@iedName by /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader @iedName - + for (Map.Entry entry : tPrivateMap.entrySet()) { + String iedName = entry.getKey(); + TPrivate tPrivate = entry.getValue(); +//if =! 1 error + List matchedStds = findStds(tPrivate, stds); + if (matchedStds.size() != 1) + throw new ScdException("There is no STD file found or there are several STD files corresponding to " + + "HeaderId = " + getValueFromPrivate(tPrivate, "headerId") + + " HeaderVersion = " + getValueFromPrivate(tPrivate, "headerVersion") + + " HeaderRevision = " + getValueFromPrivate(tPrivate, "headerRevision") + + "and ICDSystemVersionUUID = " + getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID)); + else { + //else import /dtt in Scd + // import /ied and give /ied.name = Private.iedName + SCL std = matchedStds.get(0); + SclRootAdapter stdRootAdapter = new SclRootAdapter(stds.get(0)); + scdRootAdapter.getCurrentElem().setDataTypeTemplates(std.getDataTypeTemplates()); + + //if /IED/Private/compas:ICDHeader == /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader (~3param) + IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); + /*stdIedAdapter.getCurrentElem().getPrivate() + .forEach(tp -> { + if (tp.getType().equals(COMPAS_ICDHEADER)) { + //copy 3 param into /IED/Private/compas:ICDHeader ( @BayLabel @iedName @IEDinstance) + try { + checkSTDPrivateAndLNodePrivate(tp, tPrivate); + } catch (ScdException e) { + e.getMessage(); + } + } + });*/ + + stdIedAdapter.getCurrentElem().getPrivate().stream() + .filter(tp -> tp.getType().equals(COMPAS_ICDHEADER)) + .map(tpTemp -> checkSTDPrivateAndLNodePrivate(tpTemp, tPrivate)) + .findFirst() + .orElseThrow(() -> new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED")); + + + stdIedAdapter.setIEDName(iedName); + scdRootAdapter.getCurrentElem().getIED().add(stdIedAdapter.getCurrentElem()); + + //import connectedAP (correspondance from file) + //and rename Communication/Subnetwork/ConnectedAP/@iedName by /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader @iedName + try { + addSubnetworks(scdRootAdapter.getCurrentElem(), createDefaultSubnetworkIntoSCD(iedName));//, std); + } catch (ScdException e) { + e.printStackTrace(); + } + stds.remove(std); + } + } return scdRootAdapter; } + + private static Set createDefaultSubnetworkIntoSCD(String iedName){ + final Map, List> comMap = Map.of( + Pair.of("RSPACE_PROCESS_NETWORK", "8-MMS"), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), + Pair.of("RSPACE_ADMIN_NETWORK","IP"), Arrays.asList("ADMINISTRATION_AP","TATA_AP_EFFACEC")); + Set subNetworkDTOS = new HashSet<>(); + comMap.forEach((subnetworkNameType, apNames) -> { + SubNetworkDTO subNetworkDTO = new SubNetworkDTO(subnetworkNameType.getLeft(), subnetworkNameType.getRight()); + apNames.forEach(s -> { + ConnectedApDTO connectedApDTO = new ConnectedApDTO(); + connectedApDTO.setApName(s); + connectedApDTO.setIedName(iedName); + subNetworkDTO.getConnectedAPs().add(connectedApDTO); + }); + }); + return subNetworkDTOS; + } + + private static List findStds(TPrivate tPrivate, List stds){ + List existingStds = new ArrayList<>(); + String icdSystemVersionUuid = getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID); + + stds.forEach(std -> std.getIED().forEach(ied -> ied.getPrivate().forEach(tp -> { + if (tp.getType().equals(COMPAS_ICDHEADER)) { + tp.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .forEach(o -> { + if(((Element) o).getAttribute(ICD_SYSTEM_VERSION_UUID).equals(icdSystemVersionUuid)){ + existingStds.add(std); + } + }); + } + }))); + return existingStds; + } + + private static String getValueFromPrivate(TPrivate tPrivate, String attributName) { + Element element = (Element) tPrivate.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .findFirst() + .get(); + return element.getAttribute(attributName); + } + + private static boolean checkSTDPrivateAndLNodePrivate(TPrivate iedPrivate, TPrivate scdPrivate) { + List attributNames = Arrays.asList("IEDType", "ICDSystemVersionUUID", "VendorName", "IEDredundancy", + "IEDmodel", "hwRev", "swRev", "headerId", "headerVersion", "headerRevision"); + + Element iedElement = (Element) iedPrivate.getContent().get(1); + Element scdElement = (Element) scdPrivate.getContent().get(1); + boolean isEq = attributNames.stream().map(s -> iedElement.getAttribute(s).equals(scdElement.getAttribute(s))).reduce(true, (a, b) -> a && b); + if(isEq){ + iedPrivate.getContent().clear(); + iedPrivate.getContent().add(scdElement); + return true; + } else return false; + } + + private static void checkSTDPrivateAndLNodePrivate_(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { + TCompasICDHeader compasICDHeader = getCompasICDHeader(iedPrivate); + TCompasICDHeader scdCompasICDHeader = getCompasICDHeader(scdPrivate); + String bayLabel = scdCompasICDHeader.getBayLabel(); + scdCompasICDHeader.setBayLabel(null); + String iedName = scdCompasICDHeader.getIEDName(); + scdCompasICDHeader.setIEDName(null); + String iedInstance = scdCompasICDHeader.getIEDinstance(); + scdCompasICDHeader.setIEDinstance(null); + + if(compasICDHeader.equals(scdCompasICDHeader)){ + compasICDHeader.setBayLabel(bayLabel); + compasICDHeader.setIEDinstance(iedInstance); + compasICDHeader.setIEDName(iedName); + iedPrivate.getContent().clear(); + iedPrivate.getContent().add(compasICDHeader); + } else throw new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED"); + } + + private static TCompasICDHeader getCompasICDHeader(TPrivate tPrivate) throws ScdException { + Optional headerObject = tPrivate.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .findFirst(); + if (headerObject.isPresent()) { + JAXBElement header = (JAXBElement) headerObject.get(); + return header.getValue(); + } else { + throw new ScdException("Empty COMPAS ICD HEADER Private type : " + COMPAS_ICDHEADER); + } + } + + } 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/scl/SclServiceTest.java index caeb7fc79..0723b56ee 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/scl/SclServiceTest.java @@ -4,7 +4,6 @@ package org.lfenergy.compas.sct.commons.scl; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -397,12 +396,12 @@ void testAddSubstation_SCD_With_Substation() throws Exception { } @Test - @Disabled void importIEDInSCD() throws Exception { - SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/scd_with_substation.xml"); + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_sample.xml"); + SCL std = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/std_sample.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SclRootAdapter expectedScdAdapter = SclService.importIEDInSCD(scdRootAdapter, new ArrayList<>()); + SclRootAdapter expectedScdAdapter = SclService.importIEDInSCD(scdRootAdapter, Arrays.asList(std)); } } \ No newline at end of file From cccb0a1f9cffa6879afa20ee1c3e726dd28bb3e5 Mon Sep 17 00:00:00 2001 From: SaintierFr <99645240+SaintierFr@users.noreply.github.com> Date: Fri, 22 Apr 2022 11:11:32 +0200 Subject: [PATCH 06/23] =?UTF-8?q?Update=20SCL=20communication=20import=20m?= =?UTF-8?q?ethod=20to=20allow=20the=20import=20of=20the=20att=E2=80=A6=20(?= =?UTF-8?q?#91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update SCL communication import method to allow the import of the attributes Address et PhysConn if present. Signed-off-by: SAINTIER FRANCOIS Signed-off-by: Aliou DIAITE --- sct-commons/pom.xml | 8 +- .../compas/sct/commons/scl/SclService.java | 112 +++++++----- .../commons/scl/com/CommunicationAdapter.java | 11 +- .../commons/scl/com/ConnectedAPAdapter.java | 19 ++ .../sct/commons/scl/SclServiceTest.java | 168 ++++++++++++------ .../scl/com/ConnectedAPAdapterTest.java | 69 +++++-- .../ied_with_filled_communication.xml | 111 ++++++++++++ 7 files changed, 371 insertions(+), 127 deletions(-) create mode 100644 sct-commons/src/test/resources/scl-srv-import-ieds/ied_with_filled_communication.xml diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index d8bf3c057..3f093adba 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -13,7 +13,6 @@ local-SNAPSHOT - org.lfenergy.compas sct-commons local-SNAPSHOT SCT-COMMONS @@ -21,6 +20,7 @@ ${basedir}/${aggregate.report.dir} + 3.22.0 @@ -105,6 +105,12 @@ 2.3.1 compile + + org.assertj + assertj-core + ${assertJ.version} + test + 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 index e0c2370b3..7491730da 100644 --- 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 @@ -13,6 +13,8 @@ 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; @@ -37,19 +39,22 @@ public class SclService { public static final String COMPAS_ICDHEADER = "COMPAS-ICDHeader"; public static final String ICD_SYSTEM_VERSION_UUID = "ICDSystemVersionUUID"; - private SclService(){ throw new IllegalStateException("SclService class"); } + private SclService() { + throw new IllegalStateException("SclService class"); + } public static SclRootAdapter initScl(Optional hId, String hVersion, String hRevision) throws ScdException { UUID headerId = hId.orElseGet(UUID::randomUUID); return new SclRootAdapter(headerId.toString(), hVersion, hRevision); } - public static SclRootAdapter addHistoryItem(SCL scd, String who, String what, String why){ + public static SclRootAdapter addHistoryItem(SCL scd, String who, String what, String why) { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); HeaderAdapter headerAdapter = sclRootAdapter.getHeaderAdapter(); - headerAdapter.addHistoryItem(who,what,why); + headerAdapter.addHistoryItem(who, what, why); return sclRootAdapter; } + public static SclRootAdapter updateHeader(@NonNull SCL scd, @NonNull HeaderDTO headerDTO) { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); @@ -58,17 +63,17 @@ public static SclRootAdapter updateHeader(@NonNull SCL scd, @NonNull HeaderDTO h boolean hUpdated = false; String hVersion = headerDTO.getVersion(); String hRevision = headerDTO.getRevision(); - if(hVersion != null && !hVersion.equals(headerAdapter.getHeaderVersion())){ + if (hVersion != null && !hVersion.equals(headerAdapter.getHeaderVersion())) { headerAdapter.updateVersion(hVersion); hUpdated = true; } - if(hRevision != null && !hRevision.equals(headerAdapter.getHeaderRevision())){ + if (hRevision != null && !hRevision.equals(headerAdapter.getHeaderRevision())) { headerAdapter.updateRevision(hRevision); hUpdated = true; } - if(hUpdated && !headerDTO.getHistoryItems().isEmpty()){ + if (hUpdated && !headerDTO.getHistoryItems().isEmpty()) { headerAdapter.addHistoryItem( headerDTO.getHistoryItems().get(0).getWho(), headerDTO.getHistoryItems().get(0).getWhat(), @@ -79,24 +84,32 @@ public static SclRootAdapter updateHeader(@NonNull SCL scd, @NonNull HeaderDTO h return sclRootAdapter; } - public static IEDAdapter addIED(SCL scd, String iedName, SCL icd) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - return sclRootAdapter.addIED(icd,iedName); + return sclRootAdapter.addIED(icd, iedName); } - public static Optional addSubnetworks(SCL scd, Set subNetworks) throws ScdException { + public static Optional addSubnetworks(SCL scd, Set subNetworks, Optional icd) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - CommunicationAdapter communicationAdapter = null; - if(!subNetworks.isEmpty()) { + 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()) { - communicationAdapter.addSubnetwork(snName, snType, - accessPoint.getIedName(), accessPoint.getApName()); + String iedName = accessPoint.getIedName(); + String apName = accessPoint.getApName(); + communicationAdapter.addSubnetwork(snName, snType, iedName, apName); + + Optional subNetworkAdapter = communicationAdapter.getSubnetworkByName(snName); + if (subNetworkAdapter.isPresent()) { + ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.get() + .getConnectedAPAdapter(iedName, apName); + connectedAPAdapter.copyAddressAndPhysConnFromIcd(icd); + } + } } return Optional.of(communicationAdapter); @@ -126,7 +139,7 @@ public static List getExtRefInfo(SCL scd, String iedName, String ldI public static List getExtRefBinders(SCL scd, String iedName, String ldInst, - String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException { + String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) @@ -146,14 +159,14 @@ public static List getExtRefBinders(SCL scd, String iedName, // find potential binders for the signalInfo List potentialBinders = new ArrayList<>(); - for(IEDAdapter iedA : sclRootAdapter.getIEDAdapters()){ + for (IEDAdapter iedA : sclRootAdapter.getIEDAdapters()) { potentialBinders.addAll(iedA.getExtRefBinders(signalInfo)); } return potentialBinders; } public static void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws ScdException { - if(extRefInfo.getBindingInfo() == null || extRefInfo.getSignalInfo() == null){ + if (extRefInfo.getBindingInfo() == null || extRefInfo.getSignalInfo() == null) { throw new ScdException("ExtRef Signal and/or Binding information are missing"); } String iedName = extRefInfo.getHolderIEDName(); @@ -162,11 +175,11 @@ public static void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws Sc IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) .orElseThrow( - () -> new ScdException( - String.format( - UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName - ) - ) + () -> new ScdException( + String.format( + UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName + ) + ) ); AbstractLNAdapter abstractLNAdapter = AbstractLNAdapter.builder() @@ -184,16 +197,16 @@ public static List> getExtRefSourceInfo(SCL scd, ExtRefInfo extR ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); - if(!signalInfo.isValid()){ + if (!signalInfo.isValid()) { throw new ScdException("Invalid or missing attributes in ExtRef signal info"); } ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo(); - if(!bindingInfo.isValid()){ + if (!bindingInfo.isValid()) { throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); } String iedName = extRefInfo.getHolderIEDName(); - if(bindingInfo.getIedName().equals(iedName)){ + if (bindingInfo.getIedName().equals(iedName)) { throw new ScdException("Internal binding can't have control block"); } @@ -239,18 +252,18 @@ public static TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws String prefix = extRefInfo.getHolderLnPrefix(); ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); - if(signalInfo == null || !signalInfo.isValid()){ + 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()){ + if (bindingInfo == null || !bindingInfo.isValid()) { throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); } - if(bindingInfo.getIedName().equals(iedName)){ + if (bindingInfo.getIedName().equals(iedName)) { throw new ScdException("Internal binding can't have control block"); } ExtRefSourceInfo sourceInfo = extRefInfo.getSourceInfo(); - if(sourceInfo == null || !sourceInfo.isValid()){ + if (sourceInfo == null || !sourceInfo.isValid()) { throw new ScdException(INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO); } @@ -270,9 +283,9 @@ public static TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws } public static Set getDAI(SCL scd, String iedName, String ldInst, - ResumedDataTemplate rDtt, boolean updatable) throws ScdException { + ResumedDataTemplate rDtt, boolean updatable) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iedAdapter = new IEDAdapter(sclRootAdapter,iedName); + IEDAdapter iedAdapter = new IEDAdapter(sclRootAdapter, iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) .orElseThrow( () -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName)) @@ -289,9 +302,9 @@ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedData DataTypeTemplateAdapter dttAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); LNodeTypeAdapter lNodeTypeAdapter = dttAdapter.getLNodeTypeAdapterById(rDtt.getLnType()) .orElseThrow(() -> new ScdException("Unknown LNodeType : " + rDtt.getLnType())); - lNodeTypeAdapter.check(rDtt.getDoName(),rDtt.getDaName()); + lNodeTypeAdapter.check(rDtt.getDoName(), rDtt.getDaName()); - if(TPredefinedBasicTypeEnum.OBJ_REF == rDtt.getBType()){ + if (TPredefinedBasicTypeEnum.OBJ_REF == rDtt.getBType()) { Long sGroup = rDtt.getDaName().getDaiValues().keySet().stream().findFirst().orElse(-1L); String val = sGroup < 0 ? null : rDtt.getDaName().getDaiValues().get(sGroup); sclRootAdapter.checkObjRef(val); @@ -311,8 +324,8 @@ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedData .withLnPrefix(rDtt.getPrefix()) .build(); - if(TPredefinedCDCEnum.ING == rDtt.getCdc() || TPredefinedCDCEnum.ASG == rDtt.getCdc() ){ - DAITracker daiTracker = new DAITracker(lnAdapter,rDtt.getDoName(),rDtt.getDaName()); + if (TPredefinedCDCEnum.ING == rDtt.getCdc() || TPredefinedCDCEnum.ASG == rDtt.getCdc()) { + DAITracker daiTracker = new DAITracker(lnAdapter, rDtt.getDoName(), rDtt.getDaName()); daiTracker.validateBoundedDAI(); } lnAdapter.updateDAI(rDtt); @@ -321,44 +334,45 @@ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedData public static Set> getEnumTypeElements(SCL scd, String idEnum) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - DataTypeTemplateAdapter dataTypeTemplateAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); + DataTypeTemplateAdapter dataTypeTemplateAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); EnumTypeAdapter enumTypeAdapter = dataTypeTemplateAdapter.getEnumTypeAdapterById(idEnum) - .orElseThrow(() -> new ScdException("Unknown EnumType Id: " + idEnum)); + .orElseThrow(() -> new ScdException("Unknown EnumType Id: " + idEnum)); return enumTypeAdapter.getCurrentElem().getEnumVal().stream() - .map(tEnumVal -> Pair.of(tEnumVal.getOrd(),tEnumVal.getValue())) + .map(tEnumVal -> Pair.of(tEnumVal.getOrd(), tEnumVal.getValue())) .collect(Collectors.toSet()); } public static SclRootAdapter addSubstation(@NonNull SCL scd, @NonNull SCL ssd) throws ScdException { SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); SclRootAdapter ssdRootAdapter = new SclRootAdapter(ssd); - if(scdRootAdapter.getCurrentElem().getSubstation().size() > 1 - || ssdRootAdapter.currentElem.getSubstation().size() != 1) { + if (scdRootAdapter.getCurrentElem().getSubstation().size() > 1 + || ssdRootAdapter.currentElem.getSubstation().size() != 1) { throw new ScdException("SCD file must have one or zero Substation and " + "SCD file must have one Substation. The files are rejected."); } TSubstation ssdTSubstation = ssdRootAdapter.currentElem.getSubstation().get(0); - if(scdRootAdapter.getCurrentElem().getSubstation().isEmpty()) { + if (scdRootAdapter.getCurrentElem().getSubstation().isEmpty()) { scdRootAdapter.getCurrentElem().getSubstation().add(ssdTSubstation); return scdRootAdapter; } else { TSubstation scdTSubstation = scdRootAdapter.currentElem.getSubstation().get(0); - if(scdTSubstation.getName().equalsIgnoreCase(ssdTSubstation.getName())) { + if (scdTSubstation.getName().equalsIgnoreCase(ssdTSubstation.getName())) { SubstationAdapter scdSubstationAdapter = scdRootAdapter.getSubstationAdapter(scdTSubstation.getName()); - for(TVoltageLevel tvl : ssdTSubstation.getVoltageLevel()){ + for (TVoltageLevel tvl : ssdTSubstation.getVoltageLevel()) { updateVoltageLevel(scdSubstationAdapter, tvl); } - } else throw new ScdException("SCD file must have only one Substation and the Substation name from SSD file is" + - " different from the one in SCD file. The files are rejected."); + } else + throw new ScdException("SCD file must have only one Substation and the Substation name from SSD file is" + + " different from the one in SCD file. The files are rejected."); } return scdRootAdapter; } private static void updateVoltageLevel(@NonNull SubstationAdapter scdSubstationAdapter, TVoltageLevel vl) throws ScdException { - if(scdSubstationAdapter.getVoltageLevelAdapter(vl.getName()).isPresent()) { + if (scdSubstationAdapter.getVoltageLevelAdapter(vl.getName()).isPresent()) { VoltageLevelAdapter scdVoltageLevelAdapter = scdSubstationAdapter.getVoltageLevelAdapter(vl.getName()) .orElseThrow(() -> new ScdException("Unable to create VoltageLevelAdapter")); - for (TBay tbay: vl.getBay()) { + for (TBay tbay : vl.getBay()) { updateBay(scdVoltageLevelAdapter, tbay); } } else { @@ -367,9 +381,9 @@ private static void updateVoltageLevel(@NonNull SubstationAdapter scdSubstationA } private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapter, TBay tBay) { - if(scdVoltageLevelAdapter.getBayAdapter(tBay.getName()).isPresent()){ - scdVoltageLevelAdapter.getCurrentElem().getBay() - .removeIf(t -> t.getName().equalsIgnoreCase(tBay.getName())); + if (scdVoltageLevelAdapter.getBayAdapter(tBay.getName()).isPresent()) { + scdVoltageLevelAdapter.getCurrentElem().getBay() + .removeIf(t -> t.getName().equalsIgnoreCase(tBay.getName())); scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); } else { scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java index 917ea2853..37d54dd67 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java @@ -1,4 +1,3 @@ - // SPDX-FileCopyrightText: 2021 RTE FRANCE // // SPDX-License-Identifier: Apache-2.0 @@ -43,16 +42,16 @@ public SubNetworkAdapter addSubnetwork(String snName, String snType, String iedName, String apName) throws ScdException { IEDAdapter iedAdapter = parentAdapter.getIEDAdapterByName(iedName); - if(!iedAdapter.findAccessPointByName(apName)){ + if (!iedAdapter.findAccessPointByName(apName)) { throw new ScdException("Unknown AccessPoint :" + apName + " in IED :" + iedName); } Optional opSubNetworkAdapter = getSubnetworkByName(snName); - if(!opSubNetworkAdapter.isPresent()){ // create new subnetwork + if (opSubNetworkAdapter.isEmpty()) { // create new subnetwork TSubNetwork subNetwork = new TSubNetwork(); subNetwork.setName(snName); subNetwork.setType(snType); currentElem.getSubNetwork().add(subNetwork); - opSubNetworkAdapter = Optional.of(new SubNetworkAdapter(this,subNetwork)); + opSubNetworkAdapter = Optional.of(new SubNetworkAdapter(this, subNetwork)); } opSubNetworkAdapter.get().addConnectedAP(iedName,apName); @@ -65,13 +64,13 @@ public Optional getSubnetworkByName(String snName) { .stream() .filter(tSubNetwork -> tSubNetwork.getName().equals(snName)) .findFirst() - .map(tSubNetwork -> new SubNetworkAdapter(this,tSubNetwork)); + .map(tSubNetwork -> new SubNetworkAdapter(this, tSubNetwork)); } public List getSubNetworkAdapters() { return currentElem.getSubNetwork() .stream() - .map(tSubNetwork -> new SubNetworkAdapter(this,tSubNetwork)) + .map(tSubNetwork -> new SubNetworkAdapter(this, tSubNetwork)) .collect(Collectors.toList()); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java index b0fd21141..280b15fba 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java @@ -4,10 +4,13 @@ package org.lfenergy.compas.sct.commons.scl.com; +import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TConnectedAP; import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import java.util.Optional; + public class ConnectedAPAdapter extends SclElementAdapter { public ConnectedAPAdapter(SubNetworkAdapter parentAdapter, TConnectedAP currentElem) { @@ -31,4 +34,20 @@ public String getIedName() { public String getApName() { return currentElem.getApName(); } + + public void copyAddressAndPhysConnFromIcd(Optional icd) { + if (icd.isPresent() && icd.get().getCommunication() != null) { + icd.stream() + .map(SCL::getCommunication) + .findFirst() + .flatMap(com -> com.getSubNetwork().stream() + .flatMap(subNet -> subNet.getConnectedAP().stream() + .filter(connAP -> connAP.getApName().equals(currentElem.getApName()))) + .findFirst()).ifPresent(connectedAP -> { + currentElem.setAddress(connectedAP.getAddress()); + currentElem.getPhysConn().addAll(connectedAP.getPhysConn()); + }); + + } + } } 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/scl/SclServiceTest.java index 0723b56ee..6e6ddd369 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/scl/SclServiceTest.java @@ -19,37 +19,38 @@ import java.util.*; import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; class SclServiceTest { @Test void testAddHistoryItem() throws ScdException { - SclRootAdapter sclRootAdapter= new SclRootAdapter("hId",SclRootAdapter.VERSION,SclRootAdapter.REVISION); + SclRootAdapter sclRootAdapter = new SclRootAdapter("hId", SclRootAdapter.VERSION, SclRootAdapter.REVISION); SCL scd = sclRootAdapter.getCurrentElem(); - SclService.addHistoryItem(scd,"who","what","why"); + SclService.addHistoryItem(scd, "who", "what", "why"); assertNotNull(scd.getHeader()); THeader.History history = scd.getHeader().getHistory(); assertNotNull(history); - assertEquals(1,history.getHitem().size()); + assertEquals(1, history.getHitem().size()); THitem tHitem = history.getHitem().get(0); - assertEquals("who",tHitem.getWho()); - assertEquals("what",tHitem.getWhat()); - assertEquals("why",tHitem.getWhy()); - assertEquals(SclRootAdapter.REVISION,tHitem.getRevision()); - assertEquals(SclRootAdapter.VERSION,tHitem.getVersion()); + assertEquals("who", tHitem.getWho()); + assertEquals("what", tHitem.getWhat()); + assertEquals("why", tHitem.getWhy()); + assertEquals(SclRootAdapter.REVISION, tHitem.getRevision()); + assertEquals(SclRootAdapter.VERSION, tHitem.getVersion()); } @Test void testAddIED() throws Exception { - SclRootAdapter sclRootAdapter= new SclRootAdapter("hId",SclRootAdapter.VERSION,SclRootAdapter.REVISION); + 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"); - IEDAdapter iedAdapter = assertDoesNotThrow(() -> SclService.addIED(scd,"IED_NAME1",icd)); + IEDAdapter iedAdapter = assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd)); assertEquals("IED_NAME1", iedAdapter.getName()); assertNotNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); @@ -74,11 +75,60 @@ void testAddSubnetworks() throws Exception { connectedApDTO.setIedName("IED_NAME1"); subNetworkDTO.addConnectedAP(connectedApDTO); - assertDoesNotThrow(() -> SclService.addSubnetworks(scd, Set.of(subNetworkDTO)).get()); + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, Set.of(subNetworkDTO), Optional.of(icd)).get()); MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); System.out.println(marshallerWrapper.marshall(scd)); } + @Test + void testAddSubnetworksWithoutCommunicationTagInIcd() throws Exception { + 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)); + + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, new HashSet<>(), Optional.of(icd))); + MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); + String marshalledScd = marshallerWrapper.marshall(scd); + assertThat(marshalledScd).doesNotContain(" SclService.addIED(scd, "IED_NAME1", icd)); + + Set subNetworkDTOSet = new HashSet<>(SclService.getSubnetwork(icd)); + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, subNetworkDTOSet, Optional.of(icd)).get()); + + MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); + String marshalledScd = marshallerWrapper.marshall(scd); + assertThat(marshalledScd).contains("
", "PhysConn"); + } + + @Test + void testAddSubnetworksWithoutImportingIcdAddressAndPhysConn() throws Exception { + 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)); + + Set subNetworkDTOSet = new HashSet<>(SclService.getSubnetwork(icd)); + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, subNetworkDTOSet, Optional.empty()).get()); + + MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); + String marshalledScd = marshallerWrapper.marshall(scd); + assertThat(marshalledScd).doesNotContain("
", "PhysConn"); + } + @Test void testGetSubnetwork() throws Exception { @@ -97,26 +147,26 @@ void testGetSubnetwork() throws Exception { connectedApDTO.setIedName("IED_NAME1"); subNetworkDTO.addConnectedAP(connectedApDTO); - assertDoesNotThrow(() -> SclService.addSubnetworks(scd, Set.of(subNetworkDTO)).get()); + assertDoesNotThrow(() -> SclService.addSubnetworks(scd, Set.of(subNetworkDTO), Optional.of(icd)).get()); - List subNetworkDTOS = assertDoesNotThrow(()-> SclService.getSubnetwork(scd)); - assertEquals(1,subNetworkDTOS.size()); + List subNetworkDTOS = assertDoesNotThrow(() -> SclService.getSubnetwork(scd)); + assertEquals(1, subNetworkDTOS.size()); } @Test void testGetExtRefInfo() throws Exception { - SclRootAdapter sclRootAdapter= new SclRootAdapter("hId",SclRootAdapter.VERSION,SclRootAdapter.REVISION); + 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()); + 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()); + assertEquals("IED_NAME1", extRefInfos.get(0).getHolderIEDName()); - assertThrows(ScdException.class, () -> SclService.getExtRefInfo(scd,"IED_NAME1","UNKNOWN_LD")); + assertThrows(ScdException.class, () -> SclService.getExtRefInfo(scd, "IED_NAME1", "UNKNOWN_LD")); } @Test @@ -124,36 +174,36 @@ void testGetExtRefBinders() throws Exception { 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" + "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" ); List potentialBinders = assertDoesNotThrow( () -> SclService.getExtRefBinders( - scd,"IED_NAME1","LD_INST11","LLN0","","",signalInfo + scd, "IED_NAME1", "LD_INST11", "LLN0", "", "", signalInfo ) ); assertThrows( ScdException.class, () -> SclService.getExtRefBinders( - scd,"IED_NAME1","UNKNOWN_LD","LLN0","","",signalInfo + scd, "IED_NAME1", "UNKNOWN_LD", "LLN0", "", "", signalInfo ) ); } @Test void testUpdateExtRefBinders() throws Exception { - SclRootAdapter sclRootAdapter= new SclRootAdapter("hId",SclRootAdapter.VERSION,SclRootAdapter.REVISION); + 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)); + 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" + "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" ); signalInfo.setPServT(null); signalInfo.setPLN(null); @@ -179,13 +229,13 @@ void testUpdateExtRefBinders() throws Exception { lNodeDTO.getExtRefs().add(extRefInfo); assertDoesNotThrow( - () -> SclService.updateExtRefBinders(scd,extRefInfo) + () -> SclService.updateExtRefBinders(scd, extRefInfo) ); extRefInfo.setHolderLDInst("UNKNOWN_LD"); assertThrows( ScdException.class, - () -> SclService.updateExtRefBinders( scd,extRefInfo) + () -> SclService.updateExtRefBinders(scd, extRefInfo) ); } @@ -208,10 +258,10 @@ void testGetExtRefSourceInfo() throws Exception { extRefInfo.setHolderLDInst(ldInst); extRefInfo.setHolderLnClass(lnClass); - var controlBlocks = SclService.getExtRefSourceInfo(scd,extRefInfo); - assertEquals(2,controlBlocks.size()); + var controlBlocks = SclService.getExtRefSourceInfo(scd, extRefInfo); + assertEquals(2, controlBlocks.size()); controlBlocks.forEach(controlBlock -> assertTrue( - controlBlock.getName().equals("goose1") || controlBlock.getName().equals("smv1") + controlBlock.getName().equals("goose1") || controlBlock.getName().equals("smv1") ) ); } @@ -224,21 +274,21 @@ void testUpdateExtRefSource() throws Exception { extRefInfo.setHolderLDInst("LD_INST21"); extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // signal = null + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // signal = null extRefInfo.setSignalInfo(new ExtRefSignalInfo()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // signal invalid + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // signal invalid extRefInfo.getSignalInfo().setIntAddr("INT_ADDR21"); extRefInfo.getSignalInfo().setPDA("da21.bda211.bda212.bda213"); extRefInfo.getSignalInfo().setPDO("Do21.sdo21"); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // binding = null + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // binding = null extRefInfo.setBindingInfo(new ExtRefBindingInfo()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // binding invalid + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // binding invalid extRefInfo.getBindingInfo().setIedName("IED_NAME2"); // internal binding extRefInfo.getBindingInfo().setLdInst("LD_INST12"); extRefInfo.getBindingInfo().setLnClass(TLLN0Enum.LLN_0.value()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd,extRefInfo)); // CB not allowed + assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // CB not allowed extRefInfo.getBindingInfo().setIedName("IED_NAME1"); @@ -246,12 +296,12 @@ void testUpdateExtRefSource() throws Exception { extRefInfo.getSourceInfo().setSrcLDInst(extRefInfo.getBindingInfo().getLdInst()); extRefInfo.getSourceInfo().setSrcLNClass(extRefInfo.getBindingInfo().getLnClass()); extRefInfo.getSourceInfo().setSrcCBName("goose1"); - TExtRef extRef = assertDoesNotThrow( () -> SclService.updateExtRefSource(scd,extRefInfo)); - assertEquals(extRefInfo.getSourceInfo().getSrcCBName(),extRef.getSrcCBName()); + TExtRef extRef = assertDoesNotThrow(() -> SclService.updateExtRefSource(scd, extRefInfo)); + assertEquals(extRefInfo.getSourceInfo().getSrcCBName(), extRef.getSrcCBName()); } - private ExtRefSignalInfo createSignalInfo(String pDO, String pDA, String intAddr){ + private ExtRefSignalInfo createSignalInfo(String pDO, String pDA, String intAddr) { final String DESC = "DESC"; final String P_LN = TLLN0Enum.LLN_0.value(); @@ -274,32 +324,32 @@ void testGetDAI() throws Exception { Set resumedDataTemplates = assertDoesNotThrow( - ()-> SclService.getDAI( - scd,"IED_NAME1","LD_INST12",new ResumedDataTemplate(),true + () -> SclService.getDAI( + scd, "IED_NAME1", "LD_INST12", new ResumedDataTemplate(), true ) ); - assertEquals(13,resumedDataTemplates.size()); + assertEquals(13, resumedDataTemplates.size()); assertThrows( ScdException.class, - ()-> SclService.getDAI( - scd,"IED_NAME1","UNKNOWNLD",new ResumedDataTemplate(),true + () -> SclService.getDAI( + scd, "IED_NAME1", "UNKNOWNLD", new ResumedDataTemplate(), true ) ); } @Test - void testInitScl(){ + void testInitScl() { assertDoesNotThrow( - () -> SclService.initScl(Optional.empty(), "hVersion","hRevision") + () -> SclService.initScl(Optional.empty(), "hVersion", "hRevision") ); } @Test - void testInitScl_With_hId_shouldNotThrowError(){ + void testInitScl_With_hId_shouldNotThrowError() { UUID hid = UUID.randomUUID(); assertDoesNotThrow( - () -> SclService.initScl(Optional.of(hid),"hVersion","hRevision") + () -> SclService.initScl(Optional.of(hid), "hVersion", "hRevision") ); } @@ -307,12 +357,12 @@ void testInitScl_With_hId_shouldNotThrowError(){ void testUpdateHeader() { SclRootAdapter sclRootAdapter = assertDoesNotThrow( - () -> SclService.initScl(Optional.empty(),"hVersion","hRevision") + () -> SclService.initScl(Optional.empty(), "hVersion", "hRevision") ); UUID hId = UUID.fromString(sclRootAdapter.getHeaderAdapter().getHeaderId()); HeaderDTO headerDTO = DTO.createHeaderDTO(hId); - SclService.updateHeader(sclRootAdapter.getCurrentElem(),headerDTO); - SclService.updateHeader(sclRootAdapter.getCurrentElem(),headerDTO); + SclService.updateHeader(sclRootAdapter.getCurrentElem(), headerDTO); + SclService.updateHeader(sclRootAdapter.getCurrentElem(), headerDTO); } @@ -323,8 +373,8 @@ void testUpdateDAI() throws Exception { SCL scd = SclTestMarshaller.getSCLFromFile("/ied-test-schema-conf/ied_unit_test.xml"); SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - assertThrows(ScdException.class, ()-> SclService.updateDAI( - scd,"IED","LD",rDtt + assertThrows(ScdException.class, () -> SclService.updateDAI( + scd, "IED", "LD", rDtt )); rDtt.setLnType("LNO1"); rDtt.setLnClass(TLLN0Enum.LLN_0.value()); @@ -334,17 +384,17 @@ void testUpdateDAI() throws Exception { TVal tVal = new TVal(); tVal.setValue("newValue"); rDtt.setDaiValues(List.of(tVal)); - assertDoesNotThrow(() -> SclService.updateDAI(scd,"IED_NAME","LD_INS1",rDtt)); + assertDoesNotThrow(() -> SclService.updateDAI(scd, "IED_NAME", "LD_INS1", rDtt)); } @Test void testGetEnumTypeElements() throws Exception { SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); - assertThrows(ScdException.class, ()-> SclService.getEnumTypeElements(scd,"unknwnID")); + assertThrows(ScdException.class, () -> SclService.getEnumTypeElements(scd, "unknwnID")); var enumList = assertDoesNotThrow( - ()-> SclService.getEnumTypeElements(scd,"RecCycModKind") + () -> SclService.getEnumTypeElements(scd, "RecCycModKind") ); assertFalse(enumList.isEmpty()); } @@ -356,7 +406,7 @@ void testAddSubstation_Check_SSD_Validity(String ssdFileName) throws Exception { SCL ssd = SclTestMarshaller.getSCLFromFile(ssdFileName); assertThrows(ScdException.class, - () ->SclService.addSubstation(scd, ssd)); + () -> SclService.addSubstation(scd, ssd)); } @Test @@ -377,7 +427,7 @@ void testAddSubstation_SCD_With_Different_Substation_Name() throws Exception { SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); assertThrows(ScdException.class, - () ->SclService.addSubstation(scd, ssd)); + () -> SclService.addSubstation(scd, ssd)); } @Test diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapterTest.java index 1bdc8db25..b71d8790d 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapterTest.java @@ -4,40 +4,48 @@ package org.lfenergy.compas.sct.commons.scl.com; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TConnectedAP; import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.scl2007b4.model.TSubNetwork; import org.lfenergy.compas.sct.commons.dto.DTO; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; + +import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.*; class ConnectedAPAdapterTest { - @Test - void testAmChildElementRef() { - SubNetworkAdapter subNetworkAdapter = new SubNetworkAdapter(null, new TSubNetwork()); + private SubNetworkAdapter subNetworkAdapter; + + @BeforeEach + void setUp() { + subNetworkAdapter = new SubNetworkAdapter(null, new TSubNetwork()); TConnectedAP tConnectedAP = new TConnectedAP(); tConnectedAP.setIedName(DTO.HOLDER_IED_NAME); tConnectedAP.setApName(DTO.AP_NAME); subNetworkAdapter.getCurrentElem().getConnectedAP().add(tConnectedAP); + } + @Test + void testAmChildElementRef() { ConnectedAPAdapter connectedAPAdapter = assertDoesNotThrow( - () ->subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME,DTO.AP_NAME) + () -> subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME, DTO.AP_NAME) ); - assertEquals(DTO.HOLDER_IED_NAME,connectedAPAdapter.getIedName()); - assertEquals(DTO.AP_NAME,connectedAPAdapter.getApName()); + assertEquals(DTO.HOLDER_IED_NAME, connectedAPAdapter.getIedName()); + assertEquals(DTO.AP_NAME, connectedAPAdapter.getApName()); } @Test void addPrivate() throws Exception { - SubNetworkAdapter subNetworkAdapter = new SubNetworkAdapter(null, new TSubNetwork()); - TConnectedAP tConnectedAP = new TConnectedAP(); - tConnectedAP.setIedName(DTO.HOLDER_IED_NAME); - tConnectedAP.setApName(DTO.AP_NAME); - subNetworkAdapter.getCurrentElem().getConnectedAP().add(tConnectedAP); - ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME,DTO.AP_NAME); + ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME, DTO.AP_NAME); TPrivate tPrivate = new TPrivate(); tPrivate.setType("Private Type"); tPrivate.setSource("Private Source"); @@ -45,4 +53,41 @@ void addPrivate() throws Exception { connectedAPAdapter.addPrivate(tPrivate); assertEquals(1, connectedAPAdapter.getCurrentElem().getPrivate().size()); } + + @Test + void testCopyAddressAndPhysConnFromIcd_withFilledCommunication() throws Exception { + // GIVEN + ConnectedAPAdapter connectedAPAdapter = assertDoesNotThrow( + () -> subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME, DTO.AP_NAME) + ); + + SCL icd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_with_filled_communication.xml"); + SclRootAdapter icdRootAdapter = new SclRootAdapter(icd); + Optional opIcd = Optional.of(icdRootAdapter.getCurrentElem()); + + // WHEN + connectedAPAdapter.copyAddressAndPhysConnFromIcd(opIcd); + + // THEN + assertThat(connectedAPAdapter.getCurrentElem().getAddress()).isNotNull(); + assertThat(connectedAPAdapter.getCurrentElem().getPhysConn()).isNotNull(); + assertThat(connectedAPAdapter.getCurrentElem().getGSE()).isEmpty(); + } + + @Test + void testCopyAddressAndPhysConnFromIcd_withEmptyIcd() { + // GIVEN + ConnectedAPAdapter connectedAPAdapter = assertDoesNotThrow( + () -> subNetworkAdapter.getConnectedAPAdapter(DTO.HOLDER_IED_NAME, DTO.AP_NAME) + ); + Optional opIcd = Optional.empty(); + + // WHEN + connectedAPAdapter.copyAddressAndPhysConnFromIcd(opIcd); + + // THEN + assertThat(connectedAPAdapter.getCurrentElem().getAddress()).isNull(); + assertThat(connectedAPAdapter.getCurrentElem().getPhysConn()).isEmpty(); + assertThat(connectedAPAdapter.getCurrentElem().getGSE()).isEmpty(); + } } \ No newline at end of file diff --git a/sct-commons/src/test/resources/scl-srv-import-ieds/ied_with_filled_communication.xml b/sct-commons/src/test/resources/scl-srv-import-ieds/ied_with_filled_communication.xml new file mode 100644 index 000000000..6639adcf7 --- /dev/null +++ b/sct-commons/src/test/resources/scl-srv-import-ieds/ied_with_filled_communication.xml @@ -0,0 +1,111 @@ + + + + + +
+ + + +
+

1.2.3.4

+
+ +
+

11

+
+
+ +

PL

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + myVal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Completed-diff + + + \ No newline at end of file From 962c60f579b3b86759c345ab3c8ecd38f345329c Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Wed, 20 Apr 2022 09:28:35 +0200 Subject: [PATCH 07/23] [#65] : correcting history for automation service Signed-off-by: Aliou DIAITE --- .../compas/sct/app/SclAutomationService.java | 4 ++-- .../SclAutomationServiceTest.java | 19 ------------------- 2 files changed, 2 insertions(+), 21 deletions(-) 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 7751c3b7c..260e8437d 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 @@ -23,8 +23,8 @@ public static SclRootAdapter createSCD(@NonNull SCL ssd, @NonNull HeaderDTO head SclRootAdapter scdAdapter = SclService.initScl(Optional.ofNullable(headerDTO.getId()), headerDTO.getVersion(),headerDTO.getRevision()); if(!headerDTO.getHistoryItems().isEmpty()) { - headerDTO.getHistoryItems().forEach(hItem -> - SclService.addHistoryItem(scdAdapter.getCurrentElem(), hItem.getWho(), hItem.getWhat(), hItem.getWhy())); + HeaderDTO.HistoryItem hItem = headerDTO.getHistoryItems().get(0); + SclService.addHistoryItem(scdAdapter.getCurrentElem(), hItem.getWho(), hItem.getWhat(), hItem.getWhy()); } SclService.addSubstation(scdAdapter.getCurrentElem(), ssd); return scdAdapter; 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 4732a918a..4ddfddfa2 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 @@ -12,8 +12,6 @@ import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; -import java.util.Arrays; - import static org.junit.jupiter.api.Assertions.*; class SclAutomationServiceTest { @@ -50,23 +48,6 @@ void createSCD_With_HItem() throws Exception { assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size()); } - @Test - void createSCD_With_HItems() throws Exception { - 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"); - SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO); - assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); - assertEquals(2 ,expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); - } - @Test void createSCD_SSD_Without_Substation() throws Exception { From 55dddfbc14cdfb6d6e497ca9d3c148dcd0113513 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Thu, 21 Apr 2022 09:24:27 +0200 Subject: [PATCH 08/23] [#65 ==> 95] : correcting history for automation service: add test Signed-off-by: Aliou DIAITE --- .../SclAutomationServiceTest.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) 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 4ddfddfa2..f44119d7a 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 @@ -12,6 +12,8 @@ import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import java.util.Arrays; + import static org.junit.jupiter.api.Assertions.*; class SclAutomationServiceTest { @@ -48,8 +50,25 @@ void createSCD_With_HItem() throws Exception { assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size()); } - @Test + void createSCD_With_HItems() throws Exception { + 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"); + SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO); + assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); + assertEquals(1, expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); + assertEquals("what", expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().get(0).getWhat()); + } + + @Test void createSCD_SSD_Without_Substation() throws Exception { SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml"); assertThrows(ScdException.class, From f0f9b871f6dcefaa30e700c9d2bba2dda2211e4a Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Tue, 26 Apr 2022 17:19:01 +0200 Subject: [PATCH 09/23] [#66] : WIP refactoring and test needed Signed-off-by: Aliou DIAITE --- .../compas/sct/commons/scl/SclService.java | 33 +++++++++---------- .../sct/commons/scl/SclServiceTest.java | 4 ++- 2 files changed, 19 insertions(+), 18 deletions(-) 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 index 7491730da..f2c1001f8 100644 --- 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 @@ -434,23 +434,12 @@ public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapt //if /IED/Private/compas:ICDHeader == /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader (~3param) IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); - /*stdIedAdapter.getCurrentElem().getPrivate() - .forEach(tp -> { - if (tp.getType().equals(COMPAS_ICDHEADER)) { - //copy 3 param into /IED/Private/compas:ICDHeader ( @BayLabel @iedName @IEDinstance) - try { - checkSTDPrivateAndLNodePrivate(tp, tPrivate); - } catch (ScdException e) { - e.getMessage(); - } - } - });*/ stdIedAdapter.getCurrentElem().getPrivate().stream() .filter(tp -> tp.getType().equals(COMPAS_ICDHEADER)) .map(tpTemp -> checkSTDPrivateAndLNodePrivate(tpTemp, tPrivate)) .findFirst() - .orElseThrow(() -> new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED")); + .orElseThrow(() -> new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED")); //TODO stdIedAdapter.setIEDName(iedName); @@ -459,17 +448,25 @@ public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapt //import connectedAP (correspondance from file) //and rename Communication/Subnetwork/ConnectedAP/@iedName by /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader @iedName try { - addSubnetworks(scdRootAdapter.getCurrentElem(), createDefaultSubnetworkIntoSCD(iedName));//, std); + List stdConnectedApNames = getStdConnectedApNames(std); + addSubnetworks(scdRootAdapter.getCurrentElem(), createDefaultSubnetworkIntoSCD(iedName, stdConnectedApNames), Optional.of(std)); } catch (ScdException e) { - e.printStackTrace(); + e.printStackTrace(); //TODO } - stds.remove(std); + stds.remove(std); //TODO } } return scdRootAdapter; } - private static Set createDefaultSubnetworkIntoSCD(String iedName){ + private static List getStdConnectedApNames(SCL std){ + return std.getCommunication().getSubNetwork().stream() + .map(TSubNetwork::getConnectedAP) + .flatMap(tConnectedAPS -> tConnectedAPS.stream().map(TConnectedAP::getApName)) + .collect(Collectors.toList()); + } + + private static Set createDefaultSubnetworkIntoSCD(String iedName, List stdConnectedApNames){ final Map, List> comMap = Map.of( Pair.of("RSPACE_PROCESS_NETWORK", "8-MMS"), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), Pair.of("RSPACE_ADMIN_NETWORK","IP"), Arrays.asList("ADMINISTRATION_AP","TATA_AP_EFFACEC")); @@ -477,11 +474,13 @@ private static Set createDefaultSubnetworkIntoSCD(String iedName) comMap.forEach((subnetworkNameType, apNames) -> { SubNetworkDTO subNetworkDTO = new SubNetworkDTO(subnetworkNameType.getLeft(), subnetworkNameType.getRight()); apNames.forEach(s -> { + if(stdConnectedApNames.contains(s)){ ConnectedApDTO connectedApDTO = new ConnectedApDTO(); connectedApDTO.setApName(s); connectedApDTO.setIedName(iedName); - subNetworkDTO.getConnectedAPs().add(connectedApDTO); + subNetworkDTO.addConnectedAP(connectedApDTO);} }); + subNetworkDTOS.add(subNetworkDTO); }); return subNetworkDTOS; } 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/scl/SclServiceTest.java index 6e6ddd369..306ad0758 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/scl/SclServiceTest.java @@ -4,6 +4,7 @@ package org.lfenergy.compas.sct.commons.scl; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -18,8 +19,8 @@ import java.util.*; -import static org.junit.jupiter.api.Assertions.*; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; class SclServiceTest { @@ -446,6 +447,7 @@ void testAddSubstation_SCD_With_Substation() throws Exception { } @Test + @Disabled void importIEDInSCD() throws Exception { SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_sample.xml"); SCL std = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/std_sample.xml"); From 23dcc7bce09e6b0d0849803bfe71372e8d35fbe6 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Wed, 27 Apr 2022 18:33:08 +0200 Subject: [PATCH 10/23] [#66] : WIP add files and tests, refactoring Signed-off-by: Aliou DIAITE --- .../sct/commons/dto/ConnectedApDTO.java | 5 +- .../compas/sct/commons/scl/SclService.java | 174 ++++----- .../sct/commons/scl/ied/IEDAdapter.java | 40 ++ .../sct/commons/scl/SclServiceTest.java | 48 ++- .../scd-ied-dtt-com-import-stds/scd.xml | 41 +++ .../scd_lnode_with_many_compas_icdheader.xml | 41 +++ .../scd-ied-dtt-com-import-stds/std.xml | 344 ++++++++++++++++++ .../std_SITESITE1GTW1.xml | 344 ++++++++++++++++++ .../std_SITESITE1GTW2.xml | 344 ++++++++++++++++++ .../std_with_same_ICDSystemVersionUUID.xml | 344 ++++++++++++++++++ 10 files changed, 1608 insertions(+), 117 deletions(-) create mode 100644 sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd.xml create mode 100644 sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd_lnode_with_many_compas_icdheader.xml create mode 100644 sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml create mode 100644 sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml create mode 100644 sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml create mode 100644 sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ConnectedApDTO.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ConnectedApDTO.java index 837738aca..1104525a7 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ConnectedApDTO.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ConnectedApDTO.java @@ -5,17 +5,16 @@ package org.lfenergy.compas.sct.commons.dto; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.lfenergy.compas.scl2007b4.model.TConnectedAP; import org.lfenergy.compas.sct.commons.scl.com.ConnectedAPAdapter; -import java.util.Objects; - @Setter @Getter @NoArgsConstructor +@AllArgsConstructor public class ConnectedApDTO { private String iedName; private String apName; 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 index f2c1001f8..676822312 100644 --- 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 @@ -7,7 +7,6 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; -import org.lfenergy.compas.scl.extensions.model.TCompasICDHeader; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.Utils; import org.lfenergy.compas.sct.commons.dto.*; @@ -27,7 +26,6 @@ import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter; import org.w3c.dom.Element; -import javax.xml.bind.JAXBElement; import java.util.*; import java.util.stream.Collectors; @@ -390,34 +388,16 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte } } - public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapter, List stds) throws ScdException { - // List all Private /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader - //Remove duplicated one with same iedName - + public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdRootAdapter, List stds) throws ScdException { + // List all Private and remove duplicated one with same iedName Map tPrivateMap = new HashMap<>(); - - scdRootAdapter.getCurrentElem().getSubstation().get(0).getVoltageLevel() - .forEach(tVoltageLevel -> tVoltageLevel.getBay() - .forEach(tBay -> tBay.getFunction() - .forEach(tFunction -> tFunction.getLNode() - .forEach(tlNode -> tlNode.getPrivate() - .forEach(tPrivate -> { - if (tPrivate.getType().equals(COMPAS_ICDHEADER)) { - tPrivate.getContent().stream() - .filter(o -> !o.toString().trim().isBlank()) - .forEach(o -> tPrivateMap.put((((Element) o).getAttribute("IEDName")), tPrivate)); - } - }) - ) - ) - ) - ); + getMapIEDAndPrivate(scdRootAdapter, tPrivateMap); //For each Private.ICDSystemVersionUUID and Private.iedName find STD File for (Map.Entry entry : tPrivateMap.entrySet()) { String iedName = entry.getKey(); TPrivate tPrivate = entry.getValue(); -//if =! 1 error + //if =!1 ==> error List matchedStds = findStds(tPrivate, stds); if (matchedStds.size() != 1) throw new ScdException("There is no STD file found or there are several STD files corresponding to " + @@ -426,76 +406,59 @@ public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapt " HeaderRevision = " + getValueFromPrivate(tPrivate, "headerRevision") + "and ICDSystemVersionUUID = " + getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID)); else { - //else import /dtt in Scd - // import /ied and give /ied.name = Private.iedName + // import /dtt in Scd SCL std = matchedStds.get(0); - SclRootAdapter stdRootAdapter = new SclRootAdapter(stds.get(0)); + SclRootAdapter stdRootAdapter = new SclRootAdapter(std); scdRootAdapter.getCurrentElem().setDataTypeTemplates(std.getDataTypeTemplates()); - //if /IED/Private/compas:ICDHeader == /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader (~3param) + // import /ied rename Private.iedName IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); - - stdIedAdapter.getCurrentElem().getPrivate().stream() - .filter(tp -> tp.getType().equals(COMPAS_ICDHEADER)) - .map(tpTemp -> checkSTDPrivateAndLNodePrivate(tpTemp, tPrivate)) - .findFirst() - .orElseThrow(() -> new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED")); //TODO - - + Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(COMPAS_ICDHEADER); + if(optionalTPrivate.isPresent()){ + checkSTDPrivateAndLNodePrivate(optionalTPrivate.get(), tPrivate); + } stdIedAdapter.setIEDName(iedName); scdRootAdapter.getCurrentElem().getIED().add(stdIedAdapter.getCurrentElem()); - //import connectedAP (correspondance from file) - //and rename Communication/Subnetwork/ConnectedAP/@iedName by /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader @iedName - try { - List stdConnectedApNames = getStdConnectedApNames(std); - addSubnetworks(scdRootAdapter.getCurrentElem(), createDefaultSubnetworkIntoSCD(iedName, stdConnectedApNames), Optional.of(std)); - } catch (ScdException e) { - e.printStackTrace(); //TODO - } - stds.remove(std); //TODO + //import connectedAP and rename ConnectedAP/@iedName + Set subNetworkDTOSet = createDefaultSubnetworkIntoSCD(iedName, std); + addSubnetworks(scdRootAdapter.getCurrentElem(), subNetworkDTOSet, Optional.of(std)); + // TODO remove already traited std + } } return scdRootAdapter; } - private static List getStdConnectedApNames(SCL std){ - return std.getCommunication().getSubNetwork().stream() - .map(TSubNetwork::getConnectedAP) - .flatMap(tConnectedAPS -> tConnectedAPS.stream().map(TConnectedAP::getApName)) - .collect(Collectors.toList()); - } - - private static Set createDefaultSubnetworkIntoSCD(String iedName, List stdConnectedApNames){ - final Map, List> comMap = Map.of( - Pair.of("RSPACE_PROCESS_NETWORK", "8-MMS"), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), - Pair.of("RSPACE_ADMIN_NETWORK","IP"), Arrays.asList("ADMINISTRATION_AP","TATA_AP_EFFACEC")); - Set subNetworkDTOS = new HashSet<>(); - comMap.forEach((subnetworkNameType, apNames) -> { - SubNetworkDTO subNetworkDTO = new SubNetworkDTO(subnetworkNameType.getLeft(), subnetworkNameType.getRight()); - apNames.forEach(s -> { - if(stdConnectedApNames.contains(s)){ - ConnectedApDTO connectedApDTO = new ConnectedApDTO(); - connectedApDTO.setApName(s); - connectedApDTO.setIedName(iedName); - subNetworkDTO.addConnectedAP(connectedApDTO);} - }); - subNetworkDTOS.add(subNetworkDTO); - }); - return subNetworkDTOS; + private static void getMapIEDAndPrivate(SclRootAdapter scdRootAdapter, Map tPrivateMap) { + scdRootAdapter.getCurrentElem().getSubstation().get(0).getVoltageLevel() + .forEach(tVoltageLevel -> tVoltageLevel.getBay() + .forEach(tBay -> tBay.getFunction() + .forEach(tFunction -> tFunction.getLNode() + .forEach(tlNode -> tlNode.getPrivate() + .forEach(tPrivate -> { + if (tPrivate.getType().equals(COMPAS_ICDHEADER)) { + tPrivate.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .forEach(o -> tPrivateMap.put((((Element) o).getAttribute("IEDName")), tPrivate)); + } + }) + ) + ) + ) + ); } - private static List findStds(TPrivate tPrivate, List stds){ + private static List findStds(TPrivate tPrivate, List stds) throws ScdException { List existingStds = new ArrayList<>(); String icdSystemVersionUuid = getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID); - stds.forEach(std -> std.getIED().forEach(ied -> ied.getPrivate().forEach(tp -> { if (tp.getType().equals(COMPAS_ICDHEADER)) { tp.getContent().stream() .filter(o -> !o.toString().trim().isBlank()) .forEach(o -> { if(((Element) o).getAttribute(ICD_SYSTEM_VERSION_UUID).equals(icdSystemVersionUuid)){ - existingStds.add(std); + existingStds.add(std); } }); } @@ -503,16 +466,18 @@ private static List findStds(TPrivate tPrivate, List stds){ return existingStds; } - private static String getValueFromPrivate(TPrivate tPrivate, String attributName) { - Element element = (Element) tPrivate.getContent().stream() + private static String getValueFromPrivate(TPrivate tPrivate, String attributName) throws ScdException { + Optional optionalelm = tPrivate.getContent().stream() .filter(o -> !o.toString().trim().isBlank()) - .findFirst() - .get(); - return element.getAttribute(attributName); + .findFirst(); + if(optionalelm.isPresent()){ + return ((Element) optionalelm.get()).getAttribute(attributName); + } + throw new ScdException("Attribut" + attributName +" not present in COMPAS-ICDHeader private"); } - private static boolean checkSTDPrivateAndLNodePrivate(TPrivate iedPrivate, TPrivate scdPrivate) { - List attributNames = Arrays.asList("IEDType", "ICDSystemVersionUUID", "VendorName", "IEDredundancy", + private static void checkSTDPrivateAndLNodePrivate(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { + List attributNames = Arrays.asList("IEDType", ICD_SYSTEM_VERSION_UUID, "VendorName", "IEDredundancy", "IEDmodel", "hwRev", "swRev", "headerId", "headerVersion", "headerRevision"); Element iedElement = (Element) iedPrivate.getContent().get(1); @@ -521,40 +486,33 @@ private static boolean checkSTDPrivateAndLNodePrivate(TPrivate iedPrivate, TPriv if(isEq){ iedPrivate.getContent().clear(); iedPrivate.getContent().add(scdElement); - return true; - } else return false; + } else throw new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED"); } - private static void checkSTDPrivateAndLNodePrivate_(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { - TCompasICDHeader compasICDHeader = getCompasICDHeader(iedPrivate); - TCompasICDHeader scdCompasICDHeader = getCompasICDHeader(scdPrivate); - String bayLabel = scdCompasICDHeader.getBayLabel(); - scdCompasICDHeader.setBayLabel(null); - String iedName = scdCompasICDHeader.getIEDName(); - scdCompasICDHeader.setIEDName(null); - String iedInstance = scdCompasICDHeader.getIEDinstance(); - scdCompasICDHeader.setIEDinstance(null); - - if(compasICDHeader.equals(scdCompasICDHeader)){ - compasICDHeader.setBayLabel(bayLabel); - compasICDHeader.setIEDinstance(iedInstance); - compasICDHeader.setIEDName(iedName); - iedPrivate.getContent().clear(); - iedPrivate.getContent().add(compasICDHeader); - } else throw new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED"); + private static Set createDefaultSubnetworkIntoSCD(String iedName, SCL std){ + final Map, List> comMap = Map.of( + Pair.of("RSPACE_PROCESS_NETWORK", "8-MMS"), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), + Pair.of("RSPACE_ADMIN_NETWORK","IP"), Arrays.asList("ADMIN_AP","TATA_AP_EFFACEC")); + Set subNetworkDTOS = new HashSet<>(); + comMap.forEach((subnetworkNameType, apNames) -> { + SubNetworkDTO subNetworkDTO = new SubNetworkDTO(subnetworkNameType.getLeft(), subnetworkNameType.getRight()); + apNames.forEach(s -> { + if(getStdConnectedApNames(std).contains(s)){ + ConnectedApDTO connectedApDTO = new ConnectedApDTO(iedName, s); + subNetworkDTO.addConnectedAP(connectedApDTO);} + }); + subNetworkDTOS.add(subNetworkDTO); + }); + return subNetworkDTOS; } - private static TCompasICDHeader getCompasICDHeader(TPrivate tPrivate) throws ScdException { - Optional headerObject = tPrivate.getContent().stream() - .filter(o -> !o.toString().trim().isBlank()) - .findFirst(); - if (headerObject.isPresent()) { - JAXBElement header = (JAXBElement) headerObject.get(); - return header.getValue(); - } else { - throw new ScdException("Empty COMPAS ICD HEADER Private type : " + COMPAS_ICDHEADER); - } + private static List getStdConnectedApNames(SCL std){ + return std.getCommunication().getSubNetwork().stream() + .map(TSubNetwork::getConnectedAP) + .flatMap(tConnectedAPS -> tConnectedAPS.stream().map(TConnectedAP::getApName)) + .collect(Collectors.toList()); } + } 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 6d1f8da31..daa0d77b0 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 @@ -6,6 +6,8 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; +import org.lfenergy.compas.scl.extensions.model.ObjectFactory; +import org.lfenergy.compas.scl.extensions.model.TCompasICDHeader; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.dto.ControlBlock; import org.lfenergy.compas.sct.commons.dto.DataSetInfo; @@ -16,6 +18,7 @@ import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import javax.xml.bind.JAXBElement; import java.util.*; import java.util.stream.Collectors; @@ -23,6 +26,8 @@ @Slf4j public class IEDAdapter extends SclElementAdapter { + public static final String COMPAS_ICD_HEADER = "COMPAS-ICDHeader"; + public IEDAdapter(SclRootAdapter parentAdapter) { super(parentAdapter); } @@ -259,4 +264,39 @@ public ControlBlock createControlBlock(ControlBlock getPrivateHeader(String privateType){ + return currentElem.getPrivate() + .stream() + .filter(tPrivate -> tPrivate.getType().equals(privateType)) + .findFirst(); + } + + public void createCompasICDHeader(TCompasICDHeader tIcdHeader) { + ObjectFactory objectFactory = new ObjectFactory(); + TPrivate tPrivateICDHeader = new TPrivate(); + tPrivateICDHeader.setType(IEDAdapter.COMPAS_ICD_HEADER); + JAXBElement icdHeaderElement = objectFactory.createICDHeader(tIcdHeader); + tPrivateICDHeader.getContent().add(icdHeaderElement); + currentElem.getPrivate().add(tPrivateICDHeader); + } + + public TCompasICDHeader getCompasICDHeader() throws ScdException { + Optional headerPrivate = getPrivateHeader(COMPAS_ICD_HEADER); + if (headerPrivate.isPresent()) { + Optional headerObject = headerPrivate.get().getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .findFirst(); + if (headerObject.isPresent()) { + JAXBElement header = (JAXBElement) headerObject.get(); + return header.getValue(); + } else { + throw new ScdException("Empty CoMPAS Private type : " + COMPAS_ICD_HEADER); + } + } else { + throw new ScdException("Unknown RTE Private type : " + COMPAS_ICD_HEADER); + } + } + + } 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/scl/SclServiceTest.java index 306ad0758..60f75aa7e 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/scl/SclServiceTest.java @@ -4,7 +4,6 @@ package org.lfenergy.compas.sct.commons.scl; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -447,13 +446,50 @@ void testAddSubstation_SCD_With_Substation() throws Exception { } @Test - @Disabled - void importIEDInSCD() throws Exception { - SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_sample.xml"); - SCL std = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/std_sample.xml"); + void testImportSTDElementsInSCD() throws Exception { + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd.xml"); + SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SclRootAdapter expectedScdAdapter = SclService.importIEDInSCD(scdRootAdapter, Arrays.asList(std)); + SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD(scdRootAdapter, Arrays.asList(std))); + assertThat(expectedScdAdapter.getCurrentElem().getIED()).hasSize(1); + assertThat(expectedScdAdapter.getCurrentElem().getDataTypeTemplates()).hasNoNullFieldsOrProperties(); + assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork()).hasSize(2); + } + + @Test + void testImportSTDElementsInSCD_with_Multiple_STD() throws Exception { + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd_lnode_with_many_compas_icdheader.xml"); + SCL std0 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); + SCL std1 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml"); + SCL std2 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml"); + SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + + SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD(scdRootAdapter, Arrays.asList(std0, std1, std2))); + assertThat(expectedScdAdapter.getCurrentElem().getIED()).hasSize(3); + assertThat(expectedScdAdapter.getCurrentElem().getDataTypeTemplates()).hasNoNullFieldsOrProperties(); + assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork()).hasSize(2); + assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork().get(0).getConnectedAP()).hasSize(3); + } + + @Test + void testImportSTDElementsInSCD_Several_STD_Match_Compas_ICDHeader() throws Exception { + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd.xml"); + SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); + SCL std1 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); + SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + + assertThrows(ScdException.class, () -> SclService.importSTDElementsInSCD(scdRootAdapter, Arrays.asList(std, std1))); + + } + + @Test + void importSTDElementsInSCD_Compas_ICDHeader_Not_Match() throws Exception { + 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); + + assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, Arrays.asList(std))); } } \ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd.xml new file mode 100644 index 000000000..917c8966d --- /dev/null +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd.xml @@ -0,0 +1,41 @@ + + + + + SCD + +
+ + + 0 + + + + + + + + + + + + + + + + + + + + + + diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd_lnode_with_many_compas_icdheader.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd_lnode_with_many_compas_icdheader.xml new file mode 100644 index 000000000..393510a21 --- /dev/null +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd_lnode_with_many_compas_icdheader.xml @@ -0,0 +1,41 @@ + + + + + SCD + +
+ + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml new file mode 100644 index 000000000..1e3d4da21 --- /dev/null +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml @@ -0,0 +1,344 @@ + + + + +
+ + + +
+ + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + Phase 1_Pilotes + 9d13ab59-1ec8-4c46-91c8-0326e6a5408e + 1 + 1.0 + + + + Ldevice current status + + + + + off + + + 1000 + + + Activation_deactivation command + + + + + + + + m + + + A + + + + + 10 + + + + + 20 + + + + + 20 + + + + + 10 + + + + Rated Input Current High + + + + + + + + + + + + + + + + + + + + 4800 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + on + blocked + test + test/blocked + off + + + not-supported + bay-control + station-control + remote-control + automatic-bay + automatic-station + automatic-remote + maintenance + process + + + status-only + direct-with-enhanced-security + + + + m + kg + s + A + K + mol + cd + deg + rad + sr + Gy + Bq + °C + Sv + F + C + S + H + V + ohm + J + N + Hz + lx + Lm + Wb + T + W + Pa + m² + m³ + m/s + m/s² + m³/s + m/m³ + M + kg/m³ + m²/s + W/m K + J/K + ppm + 1/s + rad/s + W/m² + J/m² + S/m + K/s + Pa/s + J/kg K + VA + Watts + VAr + phi + cos(phi) + Vs + V² + As + A² + A²t + VAh + Wh + VArh + V/Hz + Hz/s + char + char/s + kgm² + dB + J/Wh + W/s + l/s + dBm + h + min + Ohm/m + percent/s + A/V + A/Vs + + + y + z + a + f + p + n + µ + m + c + d + + da + h + k + M + G + T + P + E + Z + Y + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml new file mode 100644 index 000000000..09d31de67 --- /dev/null +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml @@ -0,0 +1,344 @@ + + + + +
+ + + +
+ + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + Phase 1_Pilotes + 9d13ab59-1ec8-4c46-91c8-0326e6a5408e + 1 + 1.0 + + + + Ldevice current status + + + + + off + + + 1000 + + + Activation_deactivation command + + + + + + + + m + + + A + + + + + 10 + + + + + 20 + + + + + 20 + + + + + 10 + + + + Rated Input Current High + + + + + + + + + + + + + + + + + + + + 4800 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + on + blocked + test + test/blocked + off + + + not-supported + bay-control + station-control + remote-control + automatic-bay + automatic-station + automatic-remote + maintenance + process + + + status-only + direct-with-enhanced-security + + + + m + kg + s + A + K + mol + cd + deg + rad + sr + Gy + Bq + °C + Sv + F + C + S + H + V + ohm + J + N + Hz + lx + Lm + Wb + T + W + Pa + m² + m³ + m/s + m/s² + m³/s + m/m³ + M + kg/m³ + m²/s + W/m K + J/K + ppm + 1/s + rad/s + W/m² + J/m² + S/m + K/s + Pa/s + J/kg K + VA + Watts + VAr + phi + cos(phi) + Vs + V² + As + A² + A²t + VAh + Wh + VArh + V/Hz + Hz/s + char + char/s + kgm² + dB + J/Wh + W/s + l/s + dBm + h + min + Ohm/m + percent/s + A/V + A/Vs + + + y + z + a + f + p + n + µ + m + c + d + + da + h + k + M + G + T + P + E + Z + Y + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml new file mode 100644 index 000000000..d9d112f2e --- /dev/null +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml @@ -0,0 +1,344 @@ + + + + +
+ + + +
+ + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + Phase 1_Pilotes + 9d13ab59-1ec8-4c46-91c8-0326e6a5408e + 1 + 1.0 + + + + Ldevice current status + + + + + off + + + 1000 + + + Activation_deactivation command + + + + + + + + m + + + A + + + + + 10 + + + + + 20 + + + + + 20 + + + + + 10 + + + + Rated Input Current High + + + + + + + + + + + + + + + + + + + + 4800 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + on + blocked + test + test/blocked + off + + + not-supported + bay-control + station-control + remote-control + automatic-bay + automatic-station + automatic-remote + maintenance + process + + + status-only + direct-with-enhanced-security + + + + m + kg + s + A + K + mol + cd + deg + rad + sr + Gy + Bq + °C + Sv + F + C + S + H + V + ohm + J + N + Hz + lx + Lm + Wb + T + W + Pa + m² + m³ + m/s + m/s² + m³/s + m/m³ + M + kg/m³ + m²/s + W/m K + J/K + ppm + 1/s + rad/s + W/m² + J/m² + S/m + K/s + Pa/s + J/kg K + VA + Watts + VAr + phi + cos(phi) + Vs + V² + As + A² + A²t + VAh + Wh + VArh + V/Hz + Hz/s + char + char/s + kgm² + dB + J/Wh + W/s + l/s + dBm + h + min + Ohm/m + percent/s + A/V + A/Vs + + + y + z + a + f + p + n + µ + m + c + d + + da + h + k + M + G + T + P + E + Z + Y + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml new file mode 100644 index 000000000..f5c7d9699 --- /dev/null +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml @@ -0,0 +1,344 @@ + + + + +
+ + + +
+ + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + Phase 1_Pilotes + 9d13ab59-1ec8-4c46-91c8-0326e6a5408e + 1 + 1.0 + + + + Ldevice current status + + + + + off + + + 1000 + + + Activation_deactivation command + + + + + + + + m + + + A + + + + + 10 + + + + + 20 + + + + + 20 + + + + + 10 + + + + Rated Input Current High + + + + + + + + + + + + + + + + + + + + 4800 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + on + blocked + test + test/blocked + off + + + not-supported + bay-control + station-control + remote-control + automatic-bay + automatic-station + automatic-remote + maintenance + process + + + status-only + direct-with-enhanced-security + + + + m + kg + s + A + K + mol + cd + deg + rad + sr + Gy + Bq + °C + Sv + F + C + S + H + V + ohm + J + N + Hz + lx + Lm + Wb + T + W + Pa + m² + m³ + m/s + m/s² + m³/s + m/m³ + M + kg/m³ + m²/s + W/m K + J/K + ppm + 1/s + rad/s + W/m² + J/m² + S/m + K/s + Pa/s + J/kg K + VA + Watts + VAr + phi + cos(phi) + Vs + V² + As + A² + A²t + VAh + Wh + VArh + V/Hz + Hz/s + char + char/s + kgm² + dB + J/Wh + W/s + l/s + dBm + h + min + Ohm/m + percent/s + A/V + A/Vs + + + y + z + a + f + p + n + µ + m + c + d + + da + h + k + M + G + T + P + E + Z + Y + + +
\ No newline at end of file From ca1d91702a4b6b1de15bb566d85a778b6feb4ce9 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Thu, 28 Apr 2022 16:57:36 +0200 Subject: [PATCH 11/23] [#66] : moving code to subnetwork and refactoring Signed-off-by: Aliou DIAITE --- .../compas/sct/commons/dto/SubNetworkDTO.java | 35 ++++++-- .../compas/sct/commons/scl/SclService.java | 90 ++++++------------- .../sct/commons/dto/SubNetworkDTOTest.java | 22 +++++ .../sct/commons/scl/SclServiceTest.java | 11 +-- .../scd-ied-dtt-com-import-stds/scd.xml | 6 -- .../scd-ied-dtt-com-import-stds/std.xml | 4 +- .../std_SITESITE1GTW1.xml | 2 +- .../std_SITESITE1GTW2.xml | 2 +- .../std_with_same_ICDSystemVersionUUID.xml | 2 +- 9 files changed, 91 insertions(+), 83 deletions(-) diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java index e71b07b04..9e186c984 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java @@ -5,17 +5,16 @@ package org.lfenergy.compas.sct.commons.dto; import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonGetter; -import com.fasterxml.jackson.annotation.JsonSetter; import com.fasterxml.jackson.annotation.JsonValue; import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; -import org.lfenergy.compas.scl2007b4.model.TSubNetwork; +import org.apache.commons.lang3.tuple.Pair; +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 java.util.HashSet; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; @Getter @@ -95,4 +94,28 @@ public static SubnetworkType fromValue(String text) { return null; } } + + public static Set createDefaultSubnetwork(String iedName, CommunicationAdapter comAdapter){ + final Map, List> comMap = Map.of( + Pair.of("RSPACE_PROCESS_NETWORK", "8-MMS"), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), + Pair.of("RSPACE_ADMIN_NETWORK","IP"), Arrays.asList("ADMINISTRATION_AP","TATA_AP_EFFACEC")); + Set subNetworkDTOS = new HashSet<>(); + comMap.forEach((subnetworkNameType, apNames) -> { + SubNetworkDTO subNetworkDTO = new SubNetworkDTO(subnetworkNameType.getLeft(), subnetworkNameType.getRight()); + apNames.forEach(s -> { + if(getStdConnectedApNames(comAdapter).contains(s)){ + ConnectedApDTO connectedApDTO = new ConnectedApDTO(iedName, s); + subNetworkDTO.addConnectedAP(connectedApDTO);} + }); + subNetworkDTOS.add(subNetworkDTO); + }); + return subNetworkDTOS; + } + + private static List getStdConnectedApNames(CommunicationAdapter comAdapter){ + return comAdapter.getSubNetworkAdapters().stream() + .map(SubNetworkAdapter::getConnectedAPAdapters) + .flatMap(connectedAPAdapters -> connectedAPAdapters.stream().map(ConnectedAPAdapter::getApName)) + .collect(Collectors.toList()); + } } 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 index 676822312..25e6c16b7 100644 --- 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 @@ -388,60 +388,55 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte } } - public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdRootAdapter, List stds) throws ScdException { + public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdRootAdapter, Set stds) throws ScdException { // List all Private and remove duplicated one with same iedName Map tPrivateMap = new HashMap<>(); - getMapIEDAndPrivate(scdRootAdapter, tPrivateMap); + createMapIEDNameAndPrivate(scdRootAdapter, tPrivateMap); //For each Private.ICDSystemVersionUUID and Private.iedName find STD File for (Map.Entry entry : tPrivateMap.entrySet()) { String iedName = entry.getKey(); TPrivate tPrivate = entry.getValue(); //if =!1 ==> error - List matchedStds = findStds(tPrivate, stds); + List matchedStds = findStds(tPrivate, stds); //TODO refactor this method, to call it once out of the loop if (matchedStds.size() != 1) throw new ScdException("There is no STD file found or there are several STD files corresponding to " + "HeaderId = " + getValueFromPrivate(tPrivate, "headerId") + " HeaderVersion = " + getValueFromPrivate(tPrivate, "headerVersion") + " HeaderRevision = " + getValueFromPrivate(tPrivate, "headerRevision") + "and ICDSystemVersionUUID = " + getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID)); - else { - // import /dtt in Scd - SCL std = matchedStds.get(0); - SclRootAdapter stdRootAdapter = new SclRootAdapter(std); - scdRootAdapter.getCurrentElem().setDataTypeTemplates(std.getDataTypeTemplates()); - - // import /ied rename Private.iedName - IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); - Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(COMPAS_ICDHEADER); - if(optionalTPrivate.isPresent()){ - checkSTDPrivateAndLNodePrivate(optionalTPrivate.get(), tPrivate); - } - stdIedAdapter.setIEDName(iedName); - scdRootAdapter.getCurrentElem().getIED().add(stdIedAdapter.getCurrentElem()); - //import connectedAP and rename ConnectedAP/@iedName - Set subNetworkDTOSet = createDefaultSubnetworkIntoSCD(iedName, std); - addSubnetworks(scdRootAdapter.getCurrentElem(), subNetworkDTOSet, Optional.of(std)); - // TODO remove already traited std + // import /dtt in Scd + SCL std = matchedStds.get(0); + SclRootAdapter stdRootAdapter = new SclRootAdapter(std); + scdRootAdapter.getCurrentElem().setDataTypeTemplates(std.getDataTypeTemplates()); + // import /ied rename Private.iedName + IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); + Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(COMPAS_ICDHEADER); + if(optionalTPrivate.isPresent()){ + checkSTDPrivateAndLNodePrivate(optionalTPrivate.get(), tPrivate); } + stdIedAdapter.setIEDName(iedName); + scdRootAdapter.getCurrentElem().getIED().add(stdIedAdapter.getCurrentElem()); + + //import connectedAP and rename ConnectedAP/@iedName + CommunicationAdapter comAdapter = stdRootAdapter.getCommunicationAdapter(false); + Set subNetworkDTOSet = SubNetworkDTO.createDefaultSubnetwork(iedName, comAdapter); + addSubnetworks(scdRootAdapter.getCurrentElem(), subNetworkDTOSet, Optional.of(std)); } return scdRootAdapter; } - private static void getMapIEDAndPrivate(SclRootAdapter scdRootAdapter, Map tPrivateMap) { + private static void createMapIEDNameAndPrivate(SclRootAdapter scdRootAdapter, Map tPrivateMap) { scdRootAdapter.getCurrentElem().getSubstation().get(0).getVoltageLevel() .forEach(tVoltageLevel -> tVoltageLevel.getBay() .forEach(tBay -> tBay.getFunction() .forEach(tFunction -> tFunction.getLNode() .forEach(tlNode -> tlNode.getPrivate() .forEach(tPrivate -> { - if (tPrivate.getType().equals(COMPAS_ICDHEADER)) { - tPrivate.getContent().stream() - .filter(o -> !o.toString().trim().isBlank()) - .forEach(o -> tPrivateMap.put((((Element) o).getAttribute("IEDName")), tPrivate)); - } + String iedName = getValueFromPrivate(tPrivate, "IEDName"); + if(iedName!= null) tPrivateMap.put(iedName, tPrivate); }) ) ) @@ -449,9 +444,10 @@ private static void getMapIEDAndPrivate(SclRootAdapter scdRootAdapter, Map findStds(TPrivate tPrivate, List stds) throws ScdException { + private static List findStds(TPrivate tPrivate, Set stds) throws ScdException { List existingStds = new ArrayList<>(); String icdSystemVersionUuid = getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID); + if(icdSystemVersionUuid == null) throw new ScdException("Attribut" + ICD_SYSTEM_VERSION_UUID +" not present in COMPAS-ICDHeader private from SCD"); stds.forEach(std -> std.getIED().forEach(ied -> ied.getPrivate().forEach(tp -> { if (tp.getType().equals(COMPAS_ICDHEADER)) { tp.getContent().stream() @@ -466,14 +462,12 @@ private static List findStds(TPrivate tPrivate, List stds) throws ScdE return existingStds; } - private static String getValueFromPrivate(TPrivate tPrivate, String attributName) throws ScdException { - Optional optionalelm = tPrivate.getContent().stream() + private static String getValueFromPrivate(TPrivate tPrivate, String attributName) { + return tPrivate.getContent().stream() .filter(o -> !o.toString().trim().isBlank()) - .findFirst(); - if(optionalelm.isPresent()){ - return ((Element) optionalelm.get()).getAttribute(attributName); - } - throw new ScdException("Attribut" + attributName +" not present in COMPAS-ICDHeader private"); + .findFirst() + .map(o -> ((Element) o).getAttribute(attributName)) + .orElse(null); } private static void checkSTDPrivateAndLNodePrivate(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { @@ -489,30 +483,4 @@ private static void checkSTDPrivateAndLNodePrivate(TPrivate iedPrivate, TPrivate } else throw new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED"); } - private static Set createDefaultSubnetworkIntoSCD(String iedName, SCL std){ - final Map, List> comMap = Map.of( - Pair.of("RSPACE_PROCESS_NETWORK", "8-MMS"), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), - Pair.of("RSPACE_ADMIN_NETWORK","IP"), Arrays.asList("ADMIN_AP","TATA_AP_EFFACEC")); - Set subNetworkDTOS = new HashSet<>(); - comMap.forEach((subnetworkNameType, apNames) -> { - SubNetworkDTO subNetworkDTO = new SubNetworkDTO(subnetworkNameType.getLeft(), subnetworkNameType.getRight()); - apNames.forEach(s -> { - if(getStdConnectedApNames(std).contains(s)){ - ConnectedApDTO connectedApDTO = new ConnectedApDTO(iedName, s); - subNetworkDTO.addConnectedAP(connectedApDTO);} - }); - subNetworkDTOS.add(subNetworkDTO); - }); - return subNetworkDTOS; - } - - private static List getStdConnectedApNames(SCL std){ - return std.getCommunication().getSubNetwork().stream() - .map(TSubNetwork::getConnectedAP) - .flatMap(tConnectedAPS -> tConnectedAPS.stream().map(TConnectedAP::getApName)) - .collect(Collectors.toList()); - } - - - } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTOTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTOTest.java index 544524bd6..489ec41f5 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTOTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTOTest.java @@ -5,12 +5,15 @@ package org.lfenergy.compas.sct.commons.dto; import org.junit.jupiter.api.Test; +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.mockito.Mockito; import java.util.List; +import java.util.Set; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; class SubNetworkDTOTest { @@ -42,4 +45,23 @@ void testFrom(){ } + @Test + void testCreateDefaultSubnetwork() { + CommunicationAdapter comAdapter = Mockito.mock(CommunicationAdapter.class); + SubNetworkAdapter subNetworkAdapter = Mockito.mock(SubNetworkAdapter.class); + ConnectedAPAdapter connectedAPAdapter = Mockito.mock(ConnectedAPAdapter.class); + + Mockito.when(comAdapter.getSubNetworkAdapters()).thenReturn(List.of(subNetworkAdapter)); + Mockito.when(subNetworkAdapter.getConnectedAPAdapters()).thenReturn(List.of(connectedAPAdapter)); + Mockito.when(subNetworkAdapter.getName()).thenReturn("sName"); + Mockito.when(subNetworkAdapter.getType()).thenReturn(SubNetworkDTO.SubnetworkType.IP.toString()); + Mockito.when(connectedAPAdapter.getApName()).thenReturn("PROCESS_AP"); + Mockito.when(connectedAPAdapter.getIedName()).thenReturn("IEDName");; + + Set subNetworkDTOS = SubNetworkDTO.createDefaultSubnetwork("IEDName", comAdapter); + assertThat(subNetworkDTOS).hasSize(2); + SubNetworkDTO expectedSubNetwork = subNetworkDTOS.stream().filter(subNetworkDTO -> !subNetworkDTO.getConnectedAPs().isEmpty()).findFirst().orElse(new SubNetworkDTO()); + assertThat(expectedSubNetwork.getConnectedAPs()).hasSize(1); + + } } \ No newline at end of file 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/scl/SclServiceTest.java index 60f75aa7e..a738c70f7 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/scl/SclServiceTest.java @@ -451,7 +451,7 @@ void testImportSTDElementsInSCD() throws Exception { SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD(scdRootAdapter, Arrays.asList(std))); + SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std))); assertThat(expectedScdAdapter.getCurrentElem().getIED()).hasSize(1); assertThat(expectedScdAdapter.getCurrentElem().getDataTypeTemplates()).hasNoNullFieldsOrProperties(); assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork()).hasSize(2); @@ -465,11 +465,12 @@ void testImportSTDElementsInSCD_with_Multiple_STD() throws Exception { SCL std2 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD(scdRootAdapter, Arrays.asList(std0, std1, std2))); + SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std0, std1, std2))); assertThat(expectedScdAdapter.getCurrentElem().getIED()).hasSize(3); assertThat(expectedScdAdapter.getCurrentElem().getDataTypeTemplates()).hasNoNullFieldsOrProperties(); assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork()).hasSize(2); - assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork().get(0).getConnectedAP()).hasSize(3); + assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork().get(0).getConnectedAP()).hasSizeBetween(1,3); + assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork().get(1).getConnectedAP()).hasSizeBetween(1,3); } @Test @@ -479,7 +480,7 @@ void testImportSTDElementsInSCD_Several_STD_Match_Compas_ICDHeader() throws Exce SCL std1 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - assertThrows(ScdException.class, () -> SclService.importSTDElementsInSCD(scdRootAdapter, Arrays.asList(std, std1))); + assertThrows(ScdException.class, () -> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std, std1))); } @@ -489,7 +490,7 @@ void importSTDElementsInSCD_Compas_ICDHeader_Not_Match() throws Exception { SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, Arrays.asList(std))); + assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std))); } } \ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd.xml index 917c8966d..5080de6e1 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/scd.xml @@ -27,12 +27,6 @@ - diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml index 1e3d4da21..8a61843b1 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml @@ -20,7 +20,7 @@ - +

Adresse IP du serveur Syslog

@@ -130,7 +130,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml index 09d31de67..021b11481 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml @@ -130,7 +130,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml index d9d112f2e..de7498536 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml @@ -130,7 +130,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml index f5c7d9699..b699b0976 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml @@ -130,7 +130,7 @@ - + From a4a898ad2d15092a4015896f35cc37bce0810a11 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Thu, 28 Apr 2022 17:22:51 +0200 Subject: [PATCH 12/23] [#66] : delete not yet used code Signed-off-by: Aliou DIAITE --- .../sct/commons/scl/ied/IEDAdapter.java | 31 ------------------- 1 file changed, 31 deletions(-) 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 daa0d77b0..9a6936557 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 @@ -6,8 +6,6 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import org.lfenergy.compas.scl.extensions.model.ObjectFactory; -import org.lfenergy.compas.scl.extensions.model.TCompasICDHeader; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.dto.ControlBlock; import org.lfenergy.compas.sct.commons.dto.DataSetInfo; @@ -18,7 +16,6 @@ import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; -import javax.xml.bind.JAXBElement; import java.util.*; import java.util.stream.Collectors; @@ -271,32 +268,4 @@ public Optional getPrivateHeader(String privateType){ .filter(tPrivate -> tPrivate.getType().equals(privateType)) .findFirst(); } - - public void createCompasICDHeader(TCompasICDHeader tIcdHeader) { - ObjectFactory objectFactory = new ObjectFactory(); - TPrivate tPrivateICDHeader = new TPrivate(); - tPrivateICDHeader.setType(IEDAdapter.COMPAS_ICD_HEADER); - JAXBElement icdHeaderElement = objectFactory.createICDHeader(tIcdHeader); - tPrivateICDHeader.getContent().add(icdHeaderElement); - currentElem.getPrivate().add(tPrivateICDHeader); - } - - public TCompasICDHeader getCompasICDHeader() throws ScdException { - Optional headerPrivate = getPrivateHeader(COMPAS_ICD_HEADER); - if (headerPrivate.isPresent()) { - Optional headerObject = headerPrivate.get().getContent().stream() - .filter(o -> !o.toString().trim().isBlank()) - .findFirst(); - if (headerObject.isPresent()) { - JAXBElement header = (JAXBElement) headerObject.get(); - return header.getValue(); - } else { - throw new ScdException("Empty CoMPAS Private type : " + COMPAS_ICD_HEADER); - } - } else { - throw new ScdException("Unknown RTE Private type : " + COMPAS_ICD_HEADER); - } - } - - } From 209711691d56a317cc10b4151c2271e1a0df5b70 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Fri, 22 Apr 2022 13:25:44 +0200 Subject: [PATCH 13/23] [#66] : WIP Signed-off-by: Aliou DIAITE --- pom.xml | 9 +++++ sct-commons/pom.xml | 6 ++- .../compas/sct/commons/scl/SclService.java | 39 +++++++++++++++++++ .../sct/commons/scl/SclServiceTest.java | 11 ++++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 8b5b10e77..5331fab3b 100644 --- a/pom.xml +++ b/pom.xml @@ -68,6 +68,11 @@ scl2007b4 0.2.1 + + org.lfenergy.compas.core + scl-extension + 0.8.0 + ch.qos.logback logback-classic @@ -80,6 +85,10 @@ org.lfenergy.compas.core scl2007b4 + + org.lfenergy.compas.core + scl-extension + ch.qos.logback logback-classic diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index 72a428b47..3f093adba 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -138,7 +138,6 @@ unpack - @@ -146,6 +145,11 @@ compas-scl-xsd 0.0.4 + + org.lfenergy.compas.core + scl-extension + 0.8.0 + ${project.build.directory} 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 index 0749d29fd..7ed2b2c40 100644 --- 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 @@ -7,6 +7,7 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; +import org.lfenergy.compas.scl.extensions.model.TCompasICDHeader; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.Utils; import org.lfenergy.compas.sct.commons.dto.*; @@ -384,4 +385,42 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); } } + + public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapter, List stds){ + + // List all Private /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader + + Map tPrivateMap = new HashMap<>(); + + scdRootAdapter.getCurrentElem().getSubstation().get(0).getVoltageLevel() + .forEach(tVoltageLevel -> tVoltageLevel.getBay() + .forEach(tBay -> tBay.getFunction() + .forEach(tFunction -> tFunction.getLNode() + .forEach(tlNode -> tlNode.getPrivate() + .forEach(tPrivate -> { + if(tPrivate.getType().equals("COMPAS-ICDHeader")){ + tPrivate.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .forEach(o -> { + TCompasICDHeader tCompasICDHeader = (TCompasICDHeader) o; + tPrivateMap.put(tCompasICDHeader.getIEDName(), tPrivate);}); + } + }) + ) + ) + ) + ); + + //Remove duplicated one with same iedName + //For each Private.ICDSystemVersionUUID and Private.iedName find STD File + //if =! 1 error + //else import /dtt in Scd + // import /ied and give /ied.name = Private.iedName + //if /IED/Private/compas:ICDHeader == /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader (~3param) + //copy 3 param into /IED/Private/compas:ICDHeader ( @BayLabel @iedName @IEDinstance) + //import connectedAP (correspondance from file) + //and rename Communication/Subnetwork/ConnectedAP/@iedName by /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader @iedName + + return scdRootAdapter; + } } 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/scl/SclServiceTest.java index b02de9717..9a7ebce8d 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/scl/SclServiceTest.java @@ -4,6 +4,7 @@ package org.lfenergy.compas.sct.commons.scl; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -444,4 +445,14 @@ void testAddSubstation_SCD_With_Substation() throws Exception { assertEquals(expectedTSubstation.getName(), tSubstation.getName()); assertEquals(expectedTSubstation.getVoltageLevel().size(), tSubstation.getVoltageLevel().size()); } + + @Test + @Disabled + void importIEDInSCD() throws Exception { + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/scd_with_substation.xml"); + SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + + SclRootAdapter expectedScdAdapter = SclService.importIEDInSCD(scdRootAdapter, new ArrayList<>()); + + } } \ No newline at end of file From a2ae4f7e1dfc933f633ac1493a48e4eba67c3564 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Tue, 26 Apr 2022 16:01:10 +0200 Subject: [PATCH 14/23] [#66] : WIP to be refactored Signed-off-by: Aliou DIAITE --- .../compas/sct/commons/scl/SclService.java | 171 ++++++++++++++++-- .../sct/commons/scl/SclServiceTest.java | 7 +- 2 files changed, 156 insertions(+), 22 deletions(-) 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 index 7ed2b2c40..7491730da 100644 --- 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 @@ -25,7 +25,9 @@ import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter; +import org.w3c.dom.Element; +import javax.xml.bind.JAXBElement; import java.util.*; import java.util.stream.Collectors; @@ -34,6 +36,8 @@ public class SclService { public static final String UNKNOWN_LDEVICE_S_IN_IED_S = "Unknown LDevice (%s) in IED (%s)"; public static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info"; + public static final String COMPAS_ICDHEADER = "COMPAS-ICDHeader"; + public static final String ICD_SYSTEM_VERSION_UUID = "ICDSystemVersionUUID"; private SclService() { throw new IllegalStateException("SclService class"); @@ -386,9 +390,9 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte } } - public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapter, List stds){ - + public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapter, List stds) throws ScdException { // List all Private /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader + //Remove duplicated one with same iedName Map tPrivateMap = new HashMap<>(); @@ -398,29 +402,160 @@ public static SclRootAdapter importIEDInSCD(@NonNull SclRootAdapter scdRootAdapt .forEach(tFunction -> tFunction.getLNode() .forEach(tlNode -> tlNode.getPrivate() .forEach(tPrivate -> { - if(tPrivate.getType().equals("COMPAS-ICDHeader")){ - tPrivate.getContent().stream() - .filter(o -> !o.toString().trim().isBlank()) - .forEach(o -> { - TCompasICDHeader tCompasICDHeader = (TCompasICDHeader) o; - tPrivateMap.put(tCompasICDHeader.getIEDName(), tPrivate);}); - } + if (tPrivate.getType().equals(COMPAS_ICDHEADER)) { + tPrivate.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .forEach(o -> tPrivateMap.put((((Element) o).getAttribute("IEDName")), tPrivate)); + } }) ) ) ) ); - //Remove duplicated one with same iedName //For each Private.ICDSystemVersionUUID and Private.iedName find STD File - //if =! 1 error - //else import /dtt in Scd - // import /ied and give /ied.name = Private.iedName - //if /IED/Private/compas:ICDHeader == /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader (~3param) - //copy 3 param into /IED/Private/compas:ICDHeader ( @BayLabel @iedName @IEDinstance) - //import connectedAP (correspondance from file) - //and rename Communication/Subnetwork/ConnectedAP/@iedName by /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader @iedName - + for (Map.Entry entry : tPrivateMap.entrySet()) { + String iedName = entry.getKey(); + TPrivate tPrivate = entry.getValue(); +//if =! 1 error + List matchedStds = findStds(tPrivate, stds); + if (matchedStds.size() != 1) + throw new ScdException("There is no STD file found or there are several STD files corresponding to " + + "HeaderId = " + getValueFromPrivate(tPrivate, "headerId") + + " HeaderVersion = " + getValueFromPrivate(tPrivate, "headerVersion") + + " HeaderRevision = " + getValueFromPrivate(tPrivate, "headerRevision") + + "and ICDSystemVersionUUID = " + getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID)); + else { + //else import /dtt in Scd + // import /ied and give /ied.name = Private.iedName + SCL std = matchedStds.get(0); + SclRootAdapter stdRootAdapter = new SclRootAdapter(stds.get(0)); + scdRootAdapter.getCurrentElem().setDataTypeTemplates(std.getDataTypeTemplates()); + + //if /IED/Private/compas:ICDHeader == /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader (~3param) + IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); + /*stdIedAdapter.getCurrentElem().getPrivate() + .forEach(tp -> { + if (tp.getType().equals(COMPAS_ICDHEADER)) { + //copy 3 param into /IED/Private/compas:ICDHeader ( @BayLabel @iedName @IEDinstance) + try { + checkSTDPrivateAndLNodePrivate(tp, tPrivate); + } catch (ScdException e) { + e.getMessage(); + } + } + });*/ + + stdIedAdapter.getCurrentElem().getPrivate().stream() + .filter(tp -> tp.getType().equals(COMPAS_ICDHEADER)) + .map(tpTemp -> checkSTDPrivateAndLNodePrivate(tpTemp, tPrivate)) + .findFirst() + .orElseThrow(() -> new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED")); + + + stdIedAdapter.setIEDName(iedName); + scdRootAdapter.getCurrentElem().getIED().add(stdIedAdapter.getCurrentElem()); + + //import connectedAP (correspondance from file) + //and rename Communication/Subnetwork/ConnectedAP/@iedName by /Substation/VoltageLevel/Bay/Function/LNode/Private/compas:ICDHeader @iedName + try { + addSubnetworks(scdRootAdapter.getCurrentElem(), createDefaultSubnetworkIntoSCD(iedName));//, std); + } catch (ScdException e) { + e.printStackTrace(); + } + stds.remove(std); + } + } return scdRootAdapter; } + + private static Set createDefaultSubnetworkIntoSCD(String iedName){ + final Map, List> comMap = Map.of( + Pair.of("RSPACE_PROCESS_NETWORK", "8-MMS"), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), + Pair.of("RSPACE_ADMIN_NETWORK","IP"), Arrays.asList("ADMINISTRATION_AP","TATA_AP_EFFACEC")); + Set subNetworkDTOS = new HashSet<>(); + comMap.forEach((subnetworkNameType, apNames) -> { + SubNetworkDTO subNetworkDTO = new SubNetworkDTO(subnetworkNameType.getLeft(), subnetworkNameType.getRight()); + apNames.forEach(s -> { + ConnectedApDTO connectedApDTO = new ConnectedApDTO(); + connectedApDTO.setApName(s); + connectedApDTO.setIedName(iedName); + subNetworkDTO.getConnectedAPs().add(connectedApDTO); + }); + }); + return subNetworkDTOS; + } + + private static List findStds(TPrivate tPrivate, List stds){ + List existingStds = new ArrayList<>(); + String icdSystemVersionUuid = getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID); + + stds.forEach(std -> std.getIED().forEach(ied -> ied.getPrivate().forEach(tp -> { + if (tp.getType().equals(COMPAS_ICDHEADER)) { + tp.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .forEach(o -> { + if(((Element) o).getAttribute(ICD_SYSTEM_VERSION_UUID).equals(icdSystemVersionUuid)){ + existingStds.add(std); + } + }); + } + }))); + return existingStds; + } + + private static String getValueFromPrivate(TPrivate tPrivate, String attributName) { + Element element = (Element) tPrivate.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .findFirst() + .get(); + return element.getAttribute(attributName); + } + + private static boolean checkSTDPrivateAndLNodePrivate(TPrivate iedPrivate, TPrivate scdPrivate) { + List attributNames = Arrays.asList("IEDType", "ICDSystemVersionUUID", "VendorName", "IEDredundancy", + "IEDmodel", "hwRev", "swRev", "headerId", "headerVersion", "headerRevision"); + + Element iedElement = (Element) iedPrivate.getContent().get(1); + Element scdElement = (Element) scdPrivate.getContent().get(1); + boolean isEq = attributNames.stream().map(s -> iedElement.getAttribute(s).equals(scdElement.getAttribute(s))).reduce(true, (a, b) -> a && b); + if(isEq){ + iedPrivate.getContent().clear(); + iedPrivate.getContent().add(scdElement); + return true; + } else return false; + } + + private static void checkSTDPrivateAndLNodePrivate_(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { + TCompasICDHeader compasICDHeader = getCompasICDHeader(iedPrivate); + TCompasICDHeader scdCompasICDHeader = getCompasICDHeader(scdPrivate); + String bayLabel = scdCompasICDHeader.getBayLabel(); + scdCompasICDHeader.setBayLabel(null); + String iedName = scdCompasICDHeader.getIEDName(); + scdCompasICDHeader.setIEDName(null); + String iedInstance = scdCompasICDHeader.getIEDinstance(); + scdCompasICDHeader.setIEDinstance(null); + + if(compasICDHeader.equals(scdCompasICDHeader)){ + compasICDHeader.setBayLabel(bayLabel); + compasICDHeader.setIEDinstance(iedInstance); + compasICDHeader.setIEDName(iedName); + iedPrivate.getContent().clear(); + iedPrivate.getContent().add(compasICDHeader); + } else throw new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED"); + } + + private static TCompasICDHeader getCompasICDHeader(TPrivate tPrivate) throws ScdException { + Optional headerObject = tPrivate.getContent().stream() + .filter(o -> !o.toString().trim().isBlank()) + .findFirst(); + if (headerObject.isPresent()) { + JAXBElement header = (JAXBElement) headerObject.get(); + return header.getValue(); + } else { + throw new ScdException("Empty COMPAS ICD HEADER Private type : " + COMPAS_ICDHEADER); + } + } + + } 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/scl/SclServiceTest.java index 9a7ebce8d..6e6ddd369 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/scl/SclServiceTest.java @@ -4,7 +4,6 @@ package org.lfenergy.compas.sct.commons.scl; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -447,12 +446,12 @@ void testAddSubstation_SCD_With_Substation() throws Exception { } @Test - @Disabled void importIEDInSCD() throws Exception { - SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/scd_with_substation.xml"); + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_sample.xml"); + SCL std = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/std_sample.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SclRootAdapter expectedScdAdapter = SclService.importIEDInSCD(scdRootAdapter, new ArrayList<>()); + SclRootAdapter expectedScdAdapter = SclService.importIEDInSCD(scdRootAdapter, Arrays.asList(std)); } } \ No newline at end of file From be8af2837c1fb55889b15a5467bc5a2a0adf6b5d Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Mon, 9 May 2022 19:05:43 +0200 Subject: [PATCH 15/23] [#66] : refactoring after remarks for pull request Signed-off-by: Aliou DIAITE --- sct-app/pom.xml | 6 + .../compas/sct/app/SclAutomationService.java | 13 +- .../SclAutomationServiceTest.java | 25 +- sct-app/src/test/resources/std_1.xml | 344 ++++++++++++++++++ sct-app/src/test/resources/std_2.xml | 344 ++++++++++++++++++ sct-app/src/test/resources/std_3.xml | 344 ++++++++++++++++++ .../compas/sct/commons/CommonConstants.java | 14 + .../compas/sct/commons/dto/SubNetworkDTO.java | 37 +- .../compas/sct/commons/scl/SclService.java | 100 ++--- .../sct/commons/scl/ied/IEDAdapter.java | 2 - .../lfenergy/compas/sct/commons/dto/DTO.java | 8 + .../sct/commons/dto/SubNetworkDTOTest.java | 11 +- .../sct/commons/scl/SclServiceTest.java | 10 +- .../scd-ied-dtt-com-import-stds/std.xml | 4 +- .../std_SITESITE1GTW1.xml | 2 +- .../std_SITESITE1GTW2.xml | 2 +- .../std_with_same_ICDSystemVersionUUID.xml | 2 +- 17 files changed, 1194 insertions(+), 74 deletions(-) create mode 100644 sct-app/src/test/resources/std_1.xml create mode 100644 sct-app/src/test/resources/std_2.xml create mode 100644 sct-app/src/test/resources/std_3.xml diff --git a/sct-app/pom.xml b/sct-app/pom.xml index 98b1a8459..a20941413 100644 --- a/sct-app/pom.xml +++ b/sct-app/pom.xml @@ -56,6 +56,12 @@ junit-jupiter-engine test + + org.mockito + mockito-core + 3.6.28 + test + 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 260e8437d..b8840930a 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 @@ -6,27 +6,34 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.tuple.Pair; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.sct.commons.dto.HeaderDTO; +import org.lfenergy.compas.sct.commons.dto.SubNetworkDTO; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.SclService; -import java.util.Optional; +import java.util.*; @Slf4j public class SclAutomationService { + private static final Map, List> comMap = Map.of( + Pair.of("RSPACE_PROCESS_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString()), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), + Pair.of("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString()), Arrays.asList("ADMIN_AP","TATA_AP_EFFACEC")); + private SclAutomationService(){throw new IllegalStateException("SclAutomationService class"); } - public static SclRootAdapter createSCD(@NonNull SCL ssd, @NonNull HeaderDTO headerDTO) throws ScdException { + public static SclRootAdapter createSCD(@NonNull SCL ssd, @NonNull HeaderDTO headerDTO, Set stds) throws ScdException { SclRootAdapter scdAdapter = SclService.initScl(Optional.ofNullable(headerDTO.getId()), headerDTO.getVersion(),headerDTO.getRevision()); if(!headerDTO.getHistoryItems().isEmpty()) { HeaderDTO.HistoryItem hItem = headerDTO.getHistoryItems().get(0); SclService.addHistoryItem(scdAdapter.getCurrentElem(), hItem.getWho(), hItem.getWhat(), hItem.getWhy()); } - SclService.addSubstation(scdAdapter.getCurrentElem(), ssd); + SclService.addSubstation(scdAdapter.getCurrentElem(), ssd); + SclService.importSTDElementsInSCD(scdAdapter, stds, comMap); return scdAdapter; } } 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 f44119d7a..6aecfd219 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 @@ -13,6 +13,8 @@ import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import static org.junit.jupiter.api.Assertions.*; @@ -29,11 +31,15 @@ void init(){ @Test void createSCD() throws Exception { - SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); - SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO); + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd.xml"); + SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); + SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std)); assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); assertNull(expectedSCD.getCurrentElem().getHeader().getHistory()); assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size()); + assertEquals(1, expectedSCD.getCurrentElem().getIED().size()); + assertNotNull(expectedSCD.getCurrentElem().getDataTypeTemplates()); + assertEquals(2, expectedSCD.getCurrentElem().getCommunication().getSubNetwork().size()); } @Test @@ -44,7 +50,10 @@ void createSCD_With_HItem() throws Exception { historyItem.setWhy("because"); headerDTO.getHistoryItems().add(historyItem); SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); - SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO); + SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); + SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml"); + SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml"); + SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std1, std2, std3)); assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); assertEquals(1 ,expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size()); @@ -62,16 +71,20 @@ void createSCD_With_HItems() throws Exception { historyItemBis.setWhy("because bis"); headerDTO.getHistoryItems().addAll(Arrays.asList(historyItem, historyItemBis)); SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); - SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO); + SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); + SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml"); + SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml"); + SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO,Set.of(std1, std2, std3)); assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); assertEquals(1, expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); assertEquals("what", expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().get(0).getWhat()); } - @Test + @Test void createSCD_SSD_Without_Substation() throws Exception { SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml"); assertThrows(ScdException.class, - () -> SclAutomationService.createSCD(ssd, headerDTO) ); + () -> SclAutomationService.createSCD(ssd, headerDTO, new HashSet<>()) ); } + } \ No newline at end of file diff --git a/sct-app/src/test/resources/std_1.xml b/sct-app/src/test/resources/std_1.xml new file mode 100644 index 000000000..a844f0fc6 --- /dev/null +++ b/sct-app/src/test/resources/std_1.xml @@ -0,0 +1,344 @@ + + + + +
+ + + +
+ + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + Phase 1_Pilotes + 9d13ab59-1ec8-4c46-91c8-0326e6a5408e + 1 + 1.0 + + + + Ldevice current status + + + + + off + + + 1000 + + + Activation_deactivation command + + + + + + + + m + + + A + + + + + 10 + + + + + 20 + + + + + 20 + + + + + 10 + + + + Rated Input Current High + + + + + + + + + + + + + + + + + + + + 4800 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + on + blocked + test + test/blocked + off + + + not-supported + bay-control + station-control + remote-control + automatic-bay + automatic-station + automatic-remote + maintenance + process + + + status-only + direct-with-enhanced-security + + + + m + kg + s + A + K + mol + cd + deg + rad + sr + Gy + Bq + °C + Sv + F + C + S + H + V + ohm + J + N + Hz + lx + Lm + Wb + T + W + Pa + m² + m³ + m/s + m/s² + m³/s + m/m³ + M + kg/m³ + m²/s + W/m K + J/K + ppm + 1/s + rad/s + W/m² + J/m² + S/m + K/s + Pa/s + J/kg K + VA + Watts + VAr + phi + cos(phi) + Vs + V² + As + A² + A²t + VAh + Wh + VArh + V/Hz + Hz/s + char + char/s + kgm² + dB + J/Wh + W/s + l/s + dBm + h + min + Ohm/m + percent/s + A/V + A/Vs + + + y + z + a + f + p + n + µ + m + c + d + + da + h + k + M + G + T + P + E + Z + Y + + +
\ No newline at end of file diff --git a/sct-app/src/test/resources/std_2.xml b/sct-app/src/test/resources/std_2.xml new file mode 100644 index 000000000..42228c889 --- /dev/null +++ b/sct-app/src/test/resources/std_2.xml @@ -0,0 +1,344 @@ + + + + +
+ + + +
+ + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + Phase 1_Pilotes + 9d13ab59-1ec8-4c46-91c8-0326e6a5408e + 1 + 1.0 + + + + Ldevice current status + + + + + off + + + 1000 + + + Activation_deactivation command + + + + + + + + m + + + A + + + + + 10 + + + + + 20 + + + + + 20 + + + + + 10 + + + + Rated Input Current High + + + + + + + + + + + + + + + + + + + + 4800 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + on + blocked + test + test/blocked + off + + + not-supported + bay-control + station-control + remote-control + automatic-bay + automatic-station + automatic-remote + maintenance + process + + + status-only + direct-with-enhanced-security + + + + m + kg + s + A + K + mol + cd + deg + rad + sr + Gy + Bq + °C + Sv + F + C + S + H + V + ohm + J + N + Hz + lx + Lm + Wb + T + W + Pa + m² + m³ + m/s + m/s² + m³/s + m/m³ + M + kg/m³ + m²/s + W/m K + J/K + ppm + 1/s + rad/s + W/m² + J/m² + S/m + K/s + Pa/s + J/kg K + VA + Watts + VAr + phi + cos(phi) + Vs + V² + As + A² + A²t + VAh + Wh + VArh + V/Hz + Hz/s + char + char/s + kgm² + dB + J/Wh + W/s + l/s + dBm + h + min + Ohm/m + percent/s + A/V + A/Vs + + + y + z + a + f + p + n + µ + m + c + d + + da + h + k + M + G + T + P + E + Z + Y + + +
\ No newline at end of file diff --git a/sct-app/src/test/resources/std_3.xml b/sct-app/src/test/resources/std_3.xml new file mode 100644 index 000000000..38ce30c55 --- /dev/null +++ b/sct-app/src/test/resources/std_3.xml @@ -0,0 +1,344 @@ + + + + +
+ + + +
+ + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + Phase 1_Pilotes + 9d13ab59-1ec8-4c46-91c8-0326e6a5408e + 1 + 1.0 + + + + Ldevice current status + + + + + off + + + 1000 + + + Activation_deactivation command + + + + + + + + m + + + A + + + + + 10 + + + + + 20 + + + + + 20 + + + + + 10 + + + + Rated Input Current High + + + + + + + + + + + + + + + + + + + + 4800 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + status-only + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + IEC 61850-8-1:2003 + + + + + + + + + IEC 61850-8-1:2003 + + + on + blocked + test + test/blocked + off + + + not-supported + bay-control + station-control + remote-control + automatic-bay + automatic-station + automatic-remote + maintenance + process + + + status-only + direct-with-enhanced-security + + + + m + kg + s + A + K + mol + cd + deg + rad + sr + Gy + Bq + °C + Sv + F + C + S + H + V + ohm + J + N + Hz + lx + Lm + Wb + T + W + Pa + m² + m³ + m/s + m/s² + m³/s + m/m³ + M + kg/m³ + m²/s + W/m K + J/K + ppm + 1/s + rad/s + W/m² + J/m² + S/m + K/s + Pa/s + J/kg K + VA + Watts + VAr + phi + cos(phi) + Vs + V² + As + A² + A²t + VAh + Wh + VArh + V/Hz + Hz/s + char + char/s + kgm² + dB + J/Wh + W/s + l/s + dBm + h + min + Ohm/m + percent/s + A/V + A/Vs + + + y + z + a + f + p + n + µ + m + c + d + + da + h + k + M + G + T + P + E + Z + Y + + +
\ No newline at end of file diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java index 01f29cbf4..48ced0b52 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java @@ -12,4 +12,18 @@ public class CommonConstants { public static final String XML_DEFAULT_NS_PREFIX = "scl"; public static final String XML_DEFAULT_NS_URI = "http://www.iec.ch/61850/2003/SCL"; public static final String XML_DEFAULT_XSD_PATH = "classpath:schema/SCL.xsd"; + + public static final String COMPAS_ICDHEADER = "COMPAS-ICDHeader"; + public static final String ICD_SYSTEM_VERSION_UUID = "ICDSystemVersionUUID"; + public static final String IED_NAME = "IEDName"; + public static final String HEADER_ID = "headerId"; + public static final String HEADER_VERSION = "headerVersion"; + public static final String HEADER_REVISION = "headerRevision"; + public static final String IED_TYPE = "IEDType"; + public static final String VENDOR_NAME = "VendorName"; + public static final String IED_REDUNDANCY = "IEDredundancy"; + public static final String IED_MODEL = "IEDmodel"; + public static final String HW_REV = "hwRev"; + public static final String SW_REV = "swRev"; + } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java index 9e186c984..e6039ef72 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java @@ -13,7 +13,10 @@ import org.lfenergy.compas.sct.commons.scl.com.ConnectedAPAdapter; import org.lfenergy.compas.sct.commons.scl.com.SubNetworkAdapter; -import java.util.*; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; @@ -95,10 +98,34 @@ public static SubnetworkType fromValue(String text) { } } - public static Set createDefaultSubnetwork(String iedName, CommunicationAdapter comAdapter){ - final Map, List> comMap = Map.of( - Pair.of("RSPACE_PROCESS_NETWORK", "8-MMS"), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), - Pair.of("RSPACE_ADMIN_NETWORK","IP"), Arrays.asList("ADMINISTRATION_AP","TATA_AP_EFFACEC")); + /* public enum SubnetworkName { + PROCESS_NETWORK("RSPACE_PROCESS_NETWORK"), // 0 + ADMIN_NETWORK("RSPACE_ADMIN_NETWORK"); // 1 + + private final String value; + + SubnetworkName(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static SubnetworkName fromValue(String text) { + for (SubnetworkName b : SubnetworkName.values()) { + if (String.valueOf(b.value).equalsIgnoreCase(text)) { + return b; + } + } + return null; + } + }*/ + + public static Set createDefaultSubnetwork(String iedName, CommunicationAdapter comAdapter, Map, List> comMap){ Set subNetworkDTOS = new HashSet<>(); comMap.forEach((subnetworkNameType, apNames) -> { SubNetworkDTO subNetworkDTO = new SubNetworkDTO(subnetworkNameType.getLeft(), subnetworkNameType.getRight()); 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 index db5dca71d..d07ee4dad 100644 --- 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 @@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.CommonConstants; import org.lfenergy.compas.sct.commons.Utils; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; @@ -34,8 +35,6 @@ public class SclService { public static final String UNKNOWN_LDEVICE_S_IN_IED_S = "Unknown LDevice (%s) in IED (%s)"; public static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info"; - public static final String COMPAS_ICDHEADER = "COMPAS-ICDHeader"; - public static final String ICD_SYSTEM_VERSION_UUID = "ICDSystemVersionUUID"; private SclService() { throw new IllegalStateException("SclService class"); @@ -388,33 +387,44 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte } } - public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdRootAdapter, Set stds) throws ScdException { - // List all Private and remove duplicated one with same iedName - Map tPrivateMap = new HashMap<>(); - createMapIEDNameAndPrivate(scdRootAdapter, tPrivateMap); + public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdRootAdapter, Set stds, + Map, List> comMap) throws ScdException { + // List all Private and remove duplicated one with same iedName + Map tPrivateMap = createMapIEDNameAndPrivate(scdRootAdapter); + + Map>> stringListMap = createMapICDSystemVersionUuidAndSTDFile(stds); + for (Map.Entry>> entry : stringListMap.entrySet()) { + if (entry.getValue().getRight().size() != 1){ + TPrivate key = entry.getValue().getLeft(); + throw new ScdException("There are several STD files corresponding to " + + CommonConstants.HEADER_ID + " = " + getValueFromPrivate(key, CommonConstants.HEADER_ID) + + CommonConstants.HEADER_VERSION + " = " + getValueFromPrivate(key, CommonConstants.HEADER_VERSION) + + CommonConstants.HEADER_REVISION + " = " + getValueFromPrivate(key, CommonConstants.HEADER_REVISION) + + "and "+ CommonConstants.ICD_SYSTEM_VERSION_UUID +" = " + getValueFromPrivate(key, CommonConstants.ICD_SYSTEM_VERSION_UUID)); } + } + //For each Private.ICDSystemVersionUUID and Private.iedName find STD File for (Map.Entry entry : tPrivateMap.entrySet()) { String iedName = entry.getKey(); TPrivate tPrivate = entry.getValue(); - //if =!1 ==> error - List matchedStds = findStds(tPrivate, stds); //TODO refactor this method, to call it once out of the loop - if (matchedStds.size() != 1) - throw new ScdException("There is no STD file found or there are several STD files corresponding to " + - "HeaderId = " + getValueFromPrivate(tPrivate, "headerId") + - " HeaderVersion = " + getValueFromPrivate(tPrivate, "headerVersion") + - " HeaderRevision = " + getValueFromPrivate(tPrivate, "headerRevision") + - "and ICDSystemVersionUUID = " + getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID)); - + String icdSysVerUuid = getValueFromPrivate(tPrivate, CommonConstants.ICD_SYSTEM_VERSION_UUID); + + if (!stringListMap.containsKey(icdSysVerUuid)) + throw new ScdException("There is no STD file found corresponding to " + + CommonConstants.HEADER_ID + " = " + getValueFromPrivate(tPrivate, CommonConstants.HEADER_ID) + + CommonConstants.HEADER_VERSION + " = " + getValueFromPrivate(tPrivate, CommonConstants.HEADER_VERSION) + + CommonConstants.HEADER_REVISION + " = " + getValueFromPrivate(tPrivate, CommonConstants.HEADER_REVISION) + + "and "+ CommonConstants.ICD_SYSTEM_VERSION_UUID +" = " + icdSysVerUuid); // import /dtt in Scd - SCL std = matchedStds.get(0); + SCL std = stringListMap.get(icdSysVerUuid).getRight().get(0); SclRootAdapter stdRootAdapter = new SclRootAdapter(std); scdRootAdapter.getCurrentElem().setDataTypeTemplates(std.getDataTypeTemplates()); // import /ied rename Private.iedName IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); - Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(COMPAS_ICDHEADER); + Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(CommonConstants.COMPAS_ICDHEADER); if(optionalTPrivate.isPresent()){ checkSTDPrivateAndLNodePrivate(optionalTPrivate.get(), tPrivate); } @@ -423,44 +433,38 @@ public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdR //import connectedAP and rename ConnectedAP/@iedName CommunicationAdapter comAdapter = stdRootAdapter.getCommunicationAdapter(false); - Set subNetworkDTOSet = SubNetworkDTO.createDefaultSubnetwork(iedName, comAdapter); + Set subNetworkDTOSet = SubNetworkDTO.createDefaultSubnetwork(iedName, comAdapter, comMap); addSubnetworks(scdRootAdapter.getCurrentElem(), subNetworkDTOSet, Optional.of(std)); } return scdRootAdapter; } - private static void createMapIEDNameAndPrivate(SclRootAdapter scdRootAdapter, Map tPrivateMap) { - scdRootAdapter.getCurrentElem().getSubstation().get(0).getVoltageLevel() - .forEach(tVoltageLevel -> tVoltageLevel.getBay() - .forEach(tBay -> tBay.getFunction() - .forEach(tFunction -> tFunction.getLNode() - .forEach(tlNode -> tlNode.getPrivate() - .forEach(tPrivate -> { - String iedName = getValueFromPrivate(tPrivate, "IEDName"); - if(iedName!= null) tPrivateMap.put(iedName, tPrivate); - }) - ) - ) - ) - ); + private static Map createMapIEDNameAndPrivate(SclRootAdapter scdRootAdapter) { + return scdRootAdapter.getCurrentElem().getSubstation().get(0).getVoltageLevel().stream() + .map(TVoltageLevel::getBay).flatMap(Collection::stream) + .map(TBay::getFunction).flatMap(Collection::stream) + .map(TFunction::getLNode).flatMap(Collection::stream) + .map(TLNode::getPrivate).flatMap(Collection::stream) + .collect(Collectors.toList()) + .stream() + .filter(tPrivate -> tPrivate.getType().equals(CommonConstants.COMPAS_ICDHEADER) && getValueFromPrivate(tPrivate, CommonConstants.IED_NAME) != null) + .collect(Collectors.toMap(tPrivate -> getValueFromPrivate(tPrivate, CommonConstants.IED_NAME), tPrivate -> tPrivate)); } - private static List findStds(TPrivate tPrivate, Set stds) throws ScdException { - List existingStds = new ArrayList<>(); - String icdSystemVersionUuid = getValueFromPrivate(tPrivate, ICD_SYSTEM_VERSION_UUID); - if(icdSystemVersionUuid == null) throw new ScdException("Attribut" + ICD_SYSTEM_VERSION_UUID +" not present in COMPAS-ICDHeader private from SCD"); + private static Map>> createMapICDSystemVersionUuidAndSTDFile(Set stds) { + Map>> stringSCLMap = new HashMap<>(); stds.forEach(std -> std.getIED().forEach(ied -> ied.getPrivate().forEach(tp -> { - if (tp.getType().equals(COMPAS_ICDHEADER)) { - tp.getContent().stream() - .filter(o -> !o.toString().trim().isBlank()) - .forEach(o -> { - if(((Element) o).getAttribute(ICD_SYSTEM_VERSION_UUID).equals(icdSystemVersionUuid)){ - existingStds.add(std); - } - }); + if (tp.getType().equals(CommonConstants.COMPAS_ICDHEADER)) { + String icdSysVer = getValueFromPrivate(tp, CommonConstants.ICD_SYSTEM_VERSION_UUID); + if(icdSysVer != null) { + Pair> pair = stringSCLMap.get(icdSysVer); + List list = pair != null ? pair.getRight() : new ArrayList<>(); + list.add(std); + stringSCLMap.put(icdSysVer, Pair.of(tp,list)); + } } }))); - return existingStds; + return stringSCLMap; } private static String getValueFromPrivate(TPrivate tPrivate, String attributName) { @@ -472,8 +476,10 @@ private static String getValueFromPrivate(TPrivate tPrivate, String attributName } private static void checkSTDPrivateAndLNodePrivate(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { - List attributNames = Arrays.asList("IEDType", ICD_SYSTEM_VERSION_UUID, "VendorName", "IEDredundancy", - "IEDmodel", "hwRev", "swRev", "headerId", "headerVersion", "headerRevision"); + List attributNames = Arrays.asList(CommonConstants.IED_TYPE, CommonConstants.ICD_SYSTEM_VERSION_UUID, + CommonConstants.VENDOR_NAME, CommonConstants.IED_REDUNDANCY, CommonConstants.IED_MODEL, + CommonConstants.HW_REV, CommonConstants.SW_REV, CommonConstants.HEADER_ID, CommonConstants.HEADER_VERSION, + CommonConstants.HEADER_REVISION); Element iedElement = (Element) iedPrivate.getContent().get(1); Element scdElement = (Element) scdPrivate.getContent().get(1); 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 9a6936557..1d79e330a 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 @@ -23,8 +23,6 @@ @Slf4j public class IEDAdapter extends SclElementAdapter { - public static final String COMPAS_ICD_HEADER = "COMPAS-ICDHeader"; - public IEDAdapter(SclRootAdapter parentAdapter) { super(parentAdapter); } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DTO.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DTO.java index 904273c5e..2ff372b10 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DTO.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DTO.java @@ -4,9 +4,13 @@ package org.lfenergy.compas.sct.commons.dto; +import org.apache.commons.lang3.tuple.Pair; import org.lfenergy.compas.scl2007b4.model.*; import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.UUID; public class DTO { @@ -288,4 +292,8 @@ public static HeaderDTO.HistoryItem createHeaderItem(String now){ return historyItem; } + + public static final Map, List> comMap = Map.of( + Pair.of("RSPACE_PROCESS_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString()), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), + Pair.of("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString()), Arrays.asList("ADMIN_AP","TATA_AP_EFFACEC")); } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTOTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTOTest.java index 489ec41f5..e9471bc07 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTOTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTOTest.java @@ -4,13 +4,16 @@ package org.lfenergy.compas.sct.commons.dto; +import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.Test; 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.mockito.Mockito; +import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -56,9 +59,13 @@ void testCreateDefaultSubnetwork() { Mockito.when(subNetworkAdapter.getName()).thenReturn("sName"); Mockito.when(subNetworkAdapter.getType()).thenReturn(SubNetworkDTO.SubnetworkType.IP.toString()); Mockito.when(connectedAPAdapter.getApName()).thenReturn("PROCESS_AP"); - Mockito.when(connectedAPAdapter.getIedName()).thenReturn("IEDName");; + Mockito.when(connectedAPAdapter.getIedName()).thenReturn("IEDName"); - Set subNetworkDTOS = SubNetworkDTO.createDefaultSubnetwork("IEDName", comAdapter); + final Map, List> comMap = Map.of( + Pair.of("RSPACE_PROCESS_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString()), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), + Pair.of("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString()), Arrays.asList("ADMIN_AP","TATA_AP_EFFACEC")); + + Set subNetworkDTOS = SubNetworkDTO.createDefaultSubnetwork("IEDName", comAdapter, comMap); assertThat(subNetworkDTOS).hasSize(2); SubNetworkDTO expectedSubNetwork = subNetworkDTOS.stream().filter(subNetworkDTO -> !subNetworkDTO.getConnectedAPs().isEmpty()).findFirst().orElse(new SubNetworkDTO()); assertThat(expectedSubNetwork.getConnectedAPs()).hasSize(1); 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/scl/SclServiceTest.java index a738c70f7..46a91e3be 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/scl/SclServiceTest.java @@ -451,7 +451,8 @@ void testImportSTDElementsInSCD() throws Exception { SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std))); + SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD( + scdRootAdapter, Set.of(std), DTO.comMap)); assertThat(expectedScdAdapter.getCurrentElem().getIED()).hasSize(1); assertThat(expectedScdAdapter.getCurrentElem().getDataTypeTemplates()).hasNoNullFieldsOrProperties(); assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork()).hasSize(2); @@ -465,7 +466,8 @@ void testImportSTDElementsInSCD_with_Multiple_STD() throws Exception { SCL std2 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std0, std1, std2))); + SclRootAdapter expectedScdAdapter = assertDoesNotThrow( () -> SclService.importSTDElementsInSCD( + scdRootAdapter, Set.of(std0, std1, std2), DTO.comMap)); assertThat(expectedScdAdapter.getCurrentElem().getIED()).hasSize(3); assertThat(expectedScdAdapter.getCurrentElem().getDataTypeTemplates()).hasNoNullFieldsOrProperties(); assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork()).hasSize(2); @@ -480,7 +482,7 @@ void testImportSTDElementsInSCD_Several_STD_Match_Compas_ICDHeader() throws Exce SCL std1 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - assertThrows(ScdException.class, () -> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std, std1))); + assertThrows(ScdException.class, () -> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std, std1), DTO.comMap)); } @@ -490,7 +492,7 @@ void importSTDElementsInSCD_Compas_ICDHeader_Not_Match() throws Exception { SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml"); SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std))); + assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std), DTO.comMap)); } } \ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml index 8a61843b1..1e3d4da21 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std.xml @@ -20,7 +20,7 @@ - +

Adresse IP du serveur Syslog

@@ -130,7 +130,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml index 021b11481..09d31de67 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW1.xml @@ -130,7 +130,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml index de7498536..d9d112f2e 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_SITESITE1GTW2.xml @@ -130,7 +130,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml index b699b0976..f5c7d9699 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml @@ -130,7 +130,7 @@ - + From e71042683c06bb98ffa5a99f0b874ea02d9eebf7 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Tue, 10 May 2022 11:52:50 +0200 Subject: [PATCH 16/23] [#66] : delete commented code and update pom.xml Signed-off-by: Aliou DIAITE --- sct-commons/pom.xml | 1 + .../compas/sct/commons/dto/SubNetworkDTO.java | 27 ------------------- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index 3f093adba..b00c180b4 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -139,6 +139,7 @@ unpack + **/SCL2007B4/*.xsd, **/SCL_CoMPAS.xsd org.lfenergy.compas.xsd diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java index e6039ef72..4dc060eb1 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SubNetworkDTO.java @@ -98,33 +98,6 @@ public static SubnetworkType fromValue(String text) { } } - /* public enum SubnetworkName { - PROCESS_NETWORK("RSPACE_PROCESS_NETWORK"), // 0 - ADMIN_NETWORK("RSPACE_ADMIN_NETWORK"); // 1 - - private final String value; - - SubnetworkName(String value) { - this.value = value; - } - - @Override - @JsonValue - public String toString() { - return String.valueOf(value); - } - - @JsonCreator - public static SubnetworkName fromValue(String text) { - for (SubnetworkName b : SubnetworkName.values()) { - if (String.valueOf(b.value).equalsIgnoreCase(text)) { - return b; - } - } - return null; - } - }*/ - public static Set createDefaultSubnetwork(String iedName, CommunicationAdapter comAdapter, Map, List> comMap){ Set subNetworkDTOS = new HashSet<>(); comMap.forEach((subnetworkNameType, apNames) -> { From 0c1184b72ed4a9aa0f352ed119ed6c5ffe6cc5cd Mon Sep 17 00:00:00 2001 From: Flurb Date: Wed, 11 May 2022 17:37:44 +0200 Subject: [PATCH 17/23] Added CII Best Practices Badge + removed unused LFX Security Tool badge Signed-off-by: Flurb --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d453ed604..2258900c2 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ SPDX-License-Identifier: Apache-2.0 --> [![REUSE status](https://api.reuse.software/badge/github.com/com-pas/compas-sct)](https://api.reuse.software/info/github.com/com-pas/compas-sct) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/5925/badge)](https://bestpractices.coreinfrastructure.org/projects/5925) # System Configuration Tool (SCT) components From 51b311debaa53d6d51a85c89184dc28ad99f17b2 Mon Sep 17 00:00:00 2001 From: aDiaite <62600667+AliouDIAITE@users.noreply.github.com> Date: Thu, 2 Jun 2022 14:41:47 +0200 Subject: [PATCH 18/23] [#88] : add private COMPAS_SCL_FILE_TYPE in created SCD (#102) [#88] : add private COMPAS_SCL_FILE_TYPE in created SCD Signed-off-by: Aliou DIAITE --- sct-app/pom.xml | 29 +++- sct-commons/pom.xml | 49 +++++- .../compas/sct/commons/CommonConstants.java | 2 + .../compas/sct/commons/scl/SclService.java | 160 ++++++++++-------- .../sct/commons/scl/SclServiceTest.java | 22 ++- .../scd-ied-dtt-com-import-stds/ssd.xml | 26 +++ .../std_with_same_ICDSystemVersionUUID.xml | 2 +- sct-coverage/pom.xml | 6 + 8 files changed, 220 insertions(+), 76 deletions(-) create mode 100644 sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/ssd.xml diff --git a/sct-app/pom.xml b/sct-app/pom.xml index a20941413..d8a715842 100644 --- a/sct-app/pom.xml +++ b/sct-app/pom.xml @@ -73,12 +73,29 @@ 11 - org.apache.maven.plugins maven-surefire-plugin - + + org.jacoco + jacoco-maven-plugin + + + default-prepare-agent + + prepare-agent + + + + report + test + + report + + + + org.apache.maven.plugins maven-dependency-plugin @@ -89,21 +106,25 @@ unpack - + **/SCL2007B4/*.xsd, **/SCL_CoMPAS.xsd org.lfenergy.compas.xsd compas-scl-xsd 0.0.4 + + org.lfenergy.compas.core + scl-extension + 0.8.0 + ${project.build.directory} -
\ No newline at end of file diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index b00c180b4..1eaf5f727 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -17,9 +17,9 @@ local-SNAPSHOT SCT-COMMONS - ${basedir}/${aggregate.report.dir} + **/scl2007b4/**/* 3.22.0 @@ -122,12 +122,34 @@ 11 - org.apache.maven.plugins maven-surefire-plugin - + + org.jacoco + jacoco-maven-plugin + + + **/scl2007b4/**/* + + + + + default-prepare-agent + + prepare-agent + + + + report + test + + report + + + + org.apache.maven.plugins maven-dependency-plugin @@ -157,6 +179,27 @@ + + org.codehaus.mojo + jaxb2-maven-plugin + 2.5.0 + + + xjc + + xjc + + + + + + ${project.build.directory}/xsd/SCL2007B4/SCL.xsd + ${project.build.directory}/xsd/SCL_CoMPAS.xsd + + org.lfenergy.compas.scl2007b4.model + true + + org.apache.maven.plugins maven-jar-plugin diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java index 48ced0b52..90dcd01b9 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java @@ -13,6 +13,8 @@ public class CommonConstants { public static final String XML_DEFAULT_NS_URI = "http://www.iec.ch/61850/2003/SCL"; public static final String XML_DEFAULT_XSD_PATH = "classpath:schema/SCL.xsd"; + public static final String COMPAS_SCL_FILE_TYPE = "COMPAS-SclFileType"; + public static final String SCL_FILE_TYPE = "SclFileType"; public static final String COMPAS_ICDHEADER = "COMPAS-ICDHeader"; public static final String ICD_SYSTEM_VERSION_UUID = "ICDSystemVersionUUID"; public static final String IED_NAME = "IEDName"; 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 index d07ee4dad..71da6181b 100644 --- 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 @@ -7,6 +7,7 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; +import org.lfenergy.compas.scl.extensions.commons.CompasExtensionsConstants; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.CommonConstants; import org.lfenergy.compas.sct.commons.Utils; @@ -25,11 +26,15 @@ import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter; -import org.w3c.dom.Element; +import javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; import java.util.*; +import java.util.function.Function; import java.util.stream.Collectors; +import static org.lfenergy.compas.sct.commons.CommonConstants.ICD_SYSTEM_VERSION_UUID; + @Slf4j public class SclService { @@ -42,7 +47,19 @@ private SclService() { public static SclRootAdapter initScl(Optional hId, String hVersion, String hRevision) throws ScdException { UUID headerId = hId.orElseGet(UUID::randomUUID); - return new SclRootAdapter(headerId.toString(), hVersion, hRevision); + SclRootAdapter scdAdapter = new SclRootAdapter(headerId.toString(), hVersion, hRevision); + scdAdapter.addPrivate(initSclFileType()); + return scdAdapter; + } + + private static TPrivate initSclFileType() { + TPrivate fileTypePrivate = new TPrivate(); + fileTypePrivate.setType(CommonConstants.COMPAS_SCL_FILE_TYPE); + JAXBElement compasFileType = new JAXBElement<>( + new QName(CompasExtensionsConstants.COMPAS_EXTENSION_NS_URI, CommonConstants.SCL_FILE_TYPE), + TCompasSclFileType.class, TCompasSclFileType.SCD); + fileTypePrivate.getContent().add(compasFileType); + return fileTypePrivate; } public static SclRootAdapter addHistoryItem(SCL scd, String who, String what, String why) { @@ -390,46 +407,30 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdRootAdapter, Set stds, Map, List> comMap) throws ScdException { - + //Check SCD and STD compatibilities + Map>> mapICDSystemVersionUuidAndSTDFile = createMapICDSystemVersionUuidAndSTDFile(stds); + checkSTDCorrespondanceWithLNodeCompasICDHeader(mapICDSystemVersionUuidAndSTDFile); // List all Private and remove duplicated one with same iedName - Map tPrivateMap = createMapIEDNameAndPrivate(scdRootAdapter); - - Map>> stringListMap = createMapICDSystemVersionUuidAndSTDFile(stds); - for (Map.Entry>> entry : stringListMap.entrySet()) { - if (entry.getValue().getRight().size() != 1){ - TPrivate key = entry.getValue().getLeft(); - throw new ScdException("There are several STD files corresponding to " + - CommonConstants.HEADER_ID + " = " + getValueFromPrivate(key, CommonConstants.HEADER_ID) + - CommonConstants.HEADER_VERSION + " = " + getValueFromPrivate(key, CommonConstants.HEADER_VERSION) + - CommonConstants.HEADER_REVISION + " = " + getValueFromPrivate(key, CommonConstants.HEADER_REVISION) + - "and "+ CommonConstants.ICD_SYSTEM_VERSION_UUID +" = " + getValueFromPrivate(key, CommonConstants.ICD_SYSTEM_VERSION_UUID)); } - } - + Map mapIEDNameAndPrivate = createMapIEDNameAndPrivate(scdRootAdapter); //For each Private.ICDSystemVersionUUID and Private.iedName find STD File - for (Map.Entry entry : tPrivateMap.entrySet()) { + for (Map.Entry entry : mapIEDNameAndPrivate.entrySet()) { String iedName = entry.getKey(); TPrivate tPrivate = entry.getValue(); - String icdSysVerUuid = getValueFromPrivate(tPrivate, CommonConstants.ICD_SYSTEM_VERSION_UUID); - - if (!stringListMap.containsKey(icdSysVerUuid)) - throw new ScdException("There is no STD file found corresponding to " + - CommonConstants.HEADER_ID + " = " + getValueFromPrivate(tPrivate, CommonConstants.HEADER_ID) + - CommonConstants.HEADER_VERSION + " = " + getValueFromPrivate(tPrivate, CommonConstants.HEADER_VERSION) + - CommonConstants.HEADER_REVISION + " = " + getValueFromPrivate(tPrivate, CommonConstants.HEADER_REVISION) + - "and "+ CommonConstants.ICD_SYSTEM_VERSION_UUID +" = " + icdSysVerUuid); - // import /dtt in Scd - SCL std = stringListMap.get(icdSysVerUuid).getRight().get(0); - SclRootAdapter stdRootAdapter = new SclRootAdapter(std); - scdRootAdapter.getCurrentElem().setDataTypeTemplates(std.getDataTypeTemplates()); + String icdSysVerUuid = getCompasICDHeader(tPrivate).map(TCompasICDHeader::getICDSystemVersionUUID).orElseThrow( + () -> new ScdException(ICD_SYSTEM_VERSION_UUID + " is not present in COMPAS-ICDHeader in LNode") + ); - // import /ied rename Private.iedName + if (!mapICDSystemVersionUuidAndSTDFile.containsKey(icdSysVerUuid)) + throw new ScdException("There is no STD file found corresponding to " + stdCheckFormatExceptionMessage(tPrivate)); + // import /ied /dtt in Scd + SCL std = mapICDSystemVersionUuidAndSTDFile.get(icdSysVerUuid).getRight().get(0); + SclRootAdapter stdRootAdapter = new SclRootAdapter(std); IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(CommonConstants.COMPAS_ICDHEADER); - if(optionalTPrivate.isPresent()){ - checkSTDPrivateAndLNodePrivate(optionalTPrivate.get(), tPrivate); - } - stdIedAdapter.setIEDName(iedName); - scdRootAdapter.getCurrentElem().getIED().add(stdIedAdapter.getCurrentElem()); + if (optionalTPrivate.isPresent() && comparePrivateCompasICDHeaders(optionalTPrivate.get(), tPrivate)) { + copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(optionalTPrivate.get(), tPrivate); + } 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 CommunicationAdapter comAdapter = stdRootAdapter.getCommunicationAdapter(false); @@ -439,54 +440,79 @@ public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdR return scdRootAdapter; } + private static void checkSTDCorrespondanceWithLNodeCompasICDHeader(Map>> mapICDSystemVersionUuidAndSTDFile) throws ScdException { + for (Pair> pairOfPrivateAndSTDs : mapICDSystemVersionUuidAndSTDFile.values()) { + if (pairOfPrivateAndSTDs.getRight().size() != 1) { + TPrivate key = pairOfPrivateAndSTDs.getLeft(); + throw new ScdException("There are several STD files corresponding to " + stdCheckFormatExceptionMessage(key)); + } + } + } + + private static String stdCheckFormatExceptionMessage(TPrivate key) { + return CommonConstants.HEADER_ID + " = " + getCompasICDHeader(key).map(TCompasICDHeader::getHeaderId).orElse(null) + + CommonConstants.HEADER_VERSION + " = " + getCompasICDHeader(key).map(TCompasICDHeader::getHeaderVersion).orElse(null) + + CommonConstants.HEADER_REVISION + " = " + getCompasICDHeader(key).map(TCompasICDHeader::getHeaderRevision).orElse(null) + + "and " + ICD_SYSTEM_VERSION_UUID + " = " + getCompasICDHeader(key).map(TCompasICDHeader::getICDSystemVersionUUID).orElse(null); + } + private static Map createMapIEDNameAndPrivate(SclRootAdapter scdRootAdapter) { return scdRootAdapter.getCurrentElem().getSubstation().get(0).getVoltageLevel().stream() .map(TVoltageLevel::getBay).flatMap(Collection::stream) .map(TBay::getFunction).flatMap(Collection::stream) .map(TFunction::getLNode).flatMap(Collection::stream) .map(TLNode::getPrivate).flatMap(Collection::stream) - .collect(Collectors.toList()) - .stream() - .filter(tPrivate -> tPrivate.getType().equals(CommonConstants.COMPAS_ICDHEADER) && getValueFromPrivate(tPrivate, CommonConstants.IED_NAME) != null) - .collect(Collectors.toMap(tPrivate -> getValueFromPrivate(tPrivate, CommonConstants.IED_NAME), tPrivate -> tPrivate)); + .filter(tPrivate -> + tPrivate.getType().equals(CommonConstants.COMPAS_ICDHEADER) + && getCompasICDHeader(tPrivate).isPresent() && getCompasICDHeader(tPrivate).get().getIEDName() != null) + .collect(Collectors.toMap(tPrivate -> getCompasICDHeader(tPrivate).get().getIEDName(), Function.identity())); } private static Map>> createMapICDSystemVersionUuidAndSTDFile(Set stds) { Map>> stringSCLMap = new HashMap<>(); stds.forEach(std -> std.getIED().forEach(ied -> ied.getPrivate().forEach(tp -> { - if (tp.getType().equals(CommonConstants.COMPAS_ICDHEADER)) { - String icdSysVer = getValueFromPrivate(tp, CommonConstants.ICD_SYSTEM_VERSION_UUID); - if(icdSysVer != null) { - Pair> pair = stringSCLMap.get(icdSysVer); - List list = pair != null ? pair.getRight() : new ArrayList<>(); - list.add(std); - stringSCLMap.put(icdSysVer, Pair.of(tp,list)); - } - } + getCompasICDHeader(tp).map(TCompasICDHeader::getICDSystemVersionUUID).ifPresent(icdSysVer -> { + Pair> pair = stringSCLMap.get(icdSysVer); + List list = pair != null ? pair.getRight() : new ArrayList<>(); + list.add(std); + stringSCLMap.put(icdSysVer, Pair.of(tp, list)); + }); }))); return stringSCLMap; } - private static String getValueFromPrivate(TPrivate tPrivate, String attributName) { - return tPrivate.getContent().stream() - .filter(o -> !o.toString().trim().isBlank()) - .findFirst() - .map(o -> ((Element) o).getAttribute(attributName)) - .orElse(null); + private static boolean comparePrivateCompasICDHeaders(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { + TCompasICDHeader iedCompasICDHeader = getCompasICDHeader(iedPrivate).orElseThrow( + () -> new ScdException(CommonConstants.COMPAS_ICDHEADER + "not found in IED Private ")); + TCompasICDHeader scdCompasICDHeader = getCompasICDHeader(scdPrivate).orElseThrow( + () -> new ScdException(CommonConstants.COMPAS_ICDHEADER + "not found in LNode Private ")); + return iedCompasICDHeader.getIEDType().equals(scdCompasICDHeader.getIEDType()) + && iedCompasICDHeader.getICDSystemVersionUUID().equals(scdCompasICDHeader.getICDSystemVersionUUID()) + && iedCompasICDHeader.getVendorName().equals(scdCompasICDHeader.getVendorName()) + && iedCompasICDHeader.getIEDredundancy().equals(scdCompasICDHeader.getIEDredundancy()) + && iedCompasICDHeader.getIEDmodel().equals(scdCompasICDHeader.getIEDmodel()) + && iedCompasICDHeader.getHwRev().equals(scdCompasICDHeader.getHwRev()) + && iedCompasICDHeader.getSwRev().equals(scdCompasICDHeader.getSwRev()) + && iedCompasICDHeader.getHeaderId().equals(scdCompasICDHeader.getHeaderId()) + && iedCompasICDHeader.getHeaderRevision().equals(scdCompasICDHeader.getHeaderRevision()) + && iedCompasICDHeader.getHeaderVersion().equals(scdCompasICDHeader.getHeaderVersion()); } - private static void checkSTDPrivateAndLNodePrivate(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { - List attributNames = Arrays.asList(CommonConstants.IED_TYPE, CommonConstants.ICD_SYSTEM_VERSION_UUID, - CommonConstants.VENDOR_NAME, CommonConstants.IED_REDUNDANCY, CommonConstants.IED_MODEL, - CommonConstants.HW_REV, CommonConstants.SW_REV, CommonConstants.HEADER_ID, CommonConstants.HEADER_VERSION, - CommonConstants.HEADER_REVISION); - - Element iedElement = (Element) iedPrivate.getContent().get(1); - Element scdElement = (Element) scdPrivate.getContent().get(1); - boolean isEq = attributNames.stream().map(s -> iedElement.getAttribute(s).equals(scdElement.getAttribute(s))).reduce(true, (a, b) -> a && b); - if(isEq){ - iedPrivate.getContent().clear(); - iedPrivate.getContent().add(scdElement); - } else throw new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED"); + private static void copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(TPrivate stdPrivate, TPrivate lNodePrivate) throws ScdException { + TCompasICDHeader lNodeCompasICDHeader = getCompasICDHeader(lNodePrivate).orElseThrow( + () -> new ScdException(CommonConstants.COMPAS_ICDHEADER + "not found in LNode Private ")); + stdPrivate.getContent().clear(); + stdPrivate.getContent().add(lNodeCompasICDHeader); + } + + private static Optional getCompasICDHeader(TPrivate tPrivate) { + Optional> tCompasICDHeader = !tPrivate.getType().equals(CommonConstants.COMPAS_ICDHEADER) ? Optional.empty() : + tPrivate.getContent().stream() + .filter(JAXBElement.class::isInstance) + .map(o -> (JAXBElement) o) + .findFirst(); + return tCompasICDHeader.map(JAXBElement::getValue); + } + } 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/scl/SclServiceTest.java index 46a91e3be..7dbc3519a 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/scl/SclServiceTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.CommonConstants; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; @@ -353,6 +354,16 @@ void testInitScl_With_hId_shouldNotThrowError() { ); } + @Test + void testInitScl_Create_Private_SCL_FILETYPE() { + UUID hid = UUID.randomUUID(); + SclRootAdapter rootAdapter = assertDoesNotThrow( + () -> SclService.initScl(Optional.of(hid), "hVersion", "hRevision") + ); + assertThat(rootAdapter.getCurrentElem().getPrivate()).isNotEmpty(); + assertThat(rootAdapter.getCurrentElem().getPrivate().get(0).getType()).isEqualTo(CommonConstants.COMPAS_SCL_FILE_TYPE); + } + @Test void testUpdateHeader() { @@ -487,7 +498,7 @@ void testImportSTDElementsInSCD_Several_STD_Match_Compas_ICDHeader() throws Exce } @Test - void importSTDElementsInSCD_Compas_ICDHeader_Not_Match() throws Exception { + void testImportSTDElementsInSCD_Compas_ICDHeader_Not_Match() throws Exception { 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); @@ -495,4 +506,13 @@ void importSTDElementsInSCD_Compas_ICDHeader_Not_Match() throws Exception { assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std), DTO.comMap)); } + + @Test + void testImportSTDElementsInSCD_No_STD_Match() throws Exception { + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/ssd.xml"); + SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + + assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, new HashSet<>(), DTO.comMap)); + + } } \ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/ssd.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/ssd.xml new file mode 100644 index 000000000..4a091c6f5 --- /dev/null +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/ssd.xml @@ -0,0 +1,26 @@ + + + + + SCD + +
+ + + 0 + + + + + + + + + + + + diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml index f5c7d9699..48aafb3cb 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml @@ -34,7 +34,7 @@ - + diff --git a/sct-coverage/pom.xml b/sct-coverage/pom.xml index 1a918db14..852a7029d 100644 --- a/sct-coverage/pom.xml +++ b/sct-coverage/pom.xml @@ -20,6 +20,7 @@ true + **/scl2007b4/**/* @@ -43,6 +44,11 @@ org.jacoco jacoco-maven-plugin + + + **/scl2007b4/**/* + + report-aggregate From 9478609c31c4c2e8173412e58ff703a300c9ec84 Mon Sep 17 00:00:00 2001 From: massifben <105049157+massifben@users.noreply.github.com> Date: Fri, 3 Jun 2022 10:17:32 +0200 Subject: [PATCH 19/23] [#70] : all updatable DA should be returned Signed-off-by: massifben <105049157+massifben@users.noreply.github.com> --- pom.xml | 4 +- .../compas/sct/commons/dto/DaTypeName.java | 32 +-- .../compas/sct/commons/dto/DataTypeName.java | 41 +-- .../compas/sct/commons/dto/DoTypeName.java | 20 +- .../compas/sct/commons/dto/LNodeDTO.java | 12 +- .../sct/commons/dto/ResumedDataTemplate.java | 60 ++-- .../compas/sct/commons/scl/SclService.java | 1 - .../sct/commons/scl/dtt/DATypeAdapter.java | 43 ++- .../sct/commons/scl/dtt/DOTypeAdapter.java | 85 +++--- .../sct/commons/scl/dtt/LNodeTypeAdapter.java | 33 +-- .../commons/scl/ied/AbstractLNAdapter.java | 122 ++++----- .../sct/commons/scl/ied/LDeviceAdapter.java | 8 +- .../sct/commons/dto/DaTypeNameTest.java | 132 +++++++-- .../sct/commons/dto/DoTypeNameTest.java | 116 ++++++-- .../compas/sct/commons/dto/LNodeDTOTest.java | 60 ++-- .../commons/dto/ResumedDataTemplateTest.java | 100 ++++++- .../sct/commons/scl/SclServiceTest.java | 194 ++++++++++++- .../commons/scl/dtt/DATypeAdapterTest.java | 7 +- .../commons/scl/dtt/DOTypeAdapterTest.java | 30 +- .../sct/commons/scl/ied/LN0AdapterTest.java | 4 +- .../commons/testhelpers/DataTypeUtils.java | 34 +++ .../testhelpers/MarshallerWrapper.java | 6 +- .../ied_test_aggregate_DAI.xml | 87 ++++++ .../ied_test_updatable_DAI.xml | 257 ++++++++++++++++++ 24 files changed, 1116 insertions(+), 372 deletions(-) create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/DataTypeUtils.java create mode 100644 sct-commons/src/test/resources/scl-srv-import-ieds/ied_test_aggregate_DAI.xml create mode 100644 sct-commons/src/test/resources/scl-srv-import-ieds/ied_test_updatable_DAI.xml diff --git a/pom.xml b/pom.xml index 5331fab3b..769f09f99 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,7 @@ org.projectlombok lombok - 1.18.20 + 1.18.24 org.junit.jupiter @@ -141,4 +141,4 @@ - \ No newline at end of file + diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DaTypeName.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DaTypeName.java index 28015bdd5..ce5166612 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DaTypeName.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DaTypeName.java @@ -4,10 +4,7 @@ package org.lfenergy.compas.sct.commons.dto; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonPropertyDescription; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -18,12 +15,12 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.stream.Collectors; @Getter @Setter @NoArgsConstructor +@EqualsAndHashCode(callSuper = true) public class DaTypeName extends DataTypeName{ public static final String VALIDATION_REGEX = "[a-zA-Z][a-zA-Z0-9]*(\\([0-9]+\\))?(\\.[a-zA-Z][a-zA-Z0-9]*(\\([0-9]+\\))?)*"; @@ -37,6 +34,10 @@ public DaTypeName(String daName) { super(daName); } + public DaTypeName(String name, String names) { + super(name, names); + } + public static DaTypeName from(DaTypeName dataName){ DaTypeName daTypeName = new DaTypeName(dataName.toString()); if(dataName.isDefined()) { @@ -50,11 +51,6 @@ public static DaTypeName from(DaTypeName dataName){ return daTypeName; } - - public DaTypeName(String name, String names) { - super(name, names); - } - public boolean isValImport(){ return valImport; } @@ -94,22 +90,6 @@ public void addDaiValue(Long sg, String val) { } } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || o.getClass() != getClass()) return false; - if (!super.equals(o)) return false; - DaTypeName that = (DaTypeName) o; - return fc == that.fc && - Objects.equals(bType, that.bType) && - Objects.equals(type, that.type); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), fc, bType, type); - } - public void merge(DaTypeName daName) { if(!isDefined()) return; fc = daName.fc; diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DataTypeName.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DataTypeName.java index 25f593173..0a09e5e1c 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DataTypeName.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DataTypeName.java @@ -5,25 +5,22 @@ package org.lfenergy.compas.sct.commons.dto; import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.NonNull; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; @Getter @Setter @Slf4j @NoArgsConstructor +@EqualsAndHashCode public class DataTypeName { protected String name = ""; // dataName or DataAttributeName @@ -31,13 +28,18 @@ public class DataTypeName { public DataTypeName(String dataName){ if(dataName == null) return; - String[] tokens = dataName.split("\\."); name = tokens[0]; if(tokens.length > 1){ - int idx = dataName.indexOf("."); - tokens = dataName.substring(idx + 1).split("\\."); - structNames = Stream.of(tokens).collect(Collectors.toList()); + structNames.addAll(List.of(tokens).subList(1, tokens.length)); + } + } + + public DataTypeName(String name, String names){ + if(name == null) return; + this.name = name; + if (StringUtils.isNotBlank(names)){ + structNames.addAll(List.of(names.split("\\."))); } } @@ -49,12 +51,6 @@ public boolean isDefined(){ return !StringUtils.isBlank(name); } - public DataTypeName(String name, @NonNull String names){ - this.name = name; - String[] tokens = names.split("\\."); - structNames = Stream.of(tokens).collect(Collectors.toList()); - } - @Override public String toString(){ StringBuilder stringBuilder = new StringBuilder(); @@ -66,21 +62,6 @@ public String toString(){ return stringBuilder.toString(); } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o==null || o.getClass() != getClass()) return false; - DataTypeName that = (DataTypeName) o; - return Objects.equals(name, that.name) && - Arrays.equals(structNames.toArray(new String[0]), - that.structNames.toArray(new String[0])); - } - - @Override - public int hashCode() { - return Objects.hash(name, structNames); - } - public void addStructName(String structName) { structNames.add(structName); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DoTypeName.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DoTypeName.java index c91301caa..c75e512f3 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DoTypeName.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DoTypeName.java @@ -4,18 +4,16 @@ package org.lfenergy.compas.sct.commons.dto; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import org.lfenergy.compas.scl2007b4.model.TPredefinedCDCEnum; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; - @Getter @Setter @NoArgsConstructor +@EqualsAndHashCode(callSuper = true) public class DoTypeName extends DataTypeName { public static final String VALIDATION_REGEX = "[A-Z][0-9A-Za-z]{0,11}(\\.[a-z][0-9A-Za-z]*(\\([0-9]+\\))?)?"; private TPredefinedCDCEnum cdc; @@ -35,20 +33,6 @@ public static DoTypeName from(DoTypeName dataName){ return doTypeName; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || o.getClass() !=getClass()) return false; - if (!super.equals(o)) return false; - DoTypeName that = (DoTypeName) o; - return cdc == that.cdc; - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), cdc); - } - public void merge(DoTypeName doName) { if(!isDefined()) return; if(cdc == null) diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LNodeDTO.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LNodeDTO.java index a3add7184..3892277b9 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LNodeDTO.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LNodeDTO.java @@ -10,8 +10,6 @@ import org.lfenergy.compas.scl2007b4.model.TAnyLN; import org.lfenergy.compas.scl2007b4.model.TExtRef; import org.lfenergy.compas.sct.commons.Utils; -import org.lfenergy.compas.sct.commons.exception.ScdException; -import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; 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.ied.AbstractLNAdapter; @@ -92,11 +90,11 @@ public static LNodeDTO from(AbstractLNAdapter nodeAdapter, ) ) ); - ResumedDataTemplate filter = new ResumedDataTemplate(); - filter.setLnInst(nodeAdapter.getLNInst()); - filter.setLnClass(nodeAdapter.getLNClass()); - filter.setPrefix(nodeAdapter.getPrefix()); - filter.setLnType(nodeAdapter.getLnType()); + ResumedDataTemplate filter = ResumedDataTemplate.builder() + .lnInst(nodeAdapter.getLNInst()) + .lnClass(nodeAdapter.getLNClass()) + .prefix(nodeAdapter.getPrefix()) + .lnType(nodeAdapter.getLnType()).build(); List resumedDataTemplateList = lNodeTypeAdapter.getResumedDTTs(filter); lNodeDTO.addAllResumedDataTemplate(resumedDataTemplateList); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplate.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplate.java index add107dba..a52514f76 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplate.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplate.java @@ -5,27 +5,30 @@ package org.lfenergy.compas.sct.commons.dto; import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import org.lfenergy.compas.scl2007b4.model.TFCEnum; -import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; -import org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum; -import org.lfenergy.compas.scl2007b4.model.TPredefinedCDCEnum; -import org.lfenergy.compas.scl2007b4.model.TVal; +import lombok.*; +import org.lfenergy.compas.scl2007b4.model.*; + +import java.util.ArrayList; +import java.util.List; -import java.util.*; @Setter @Getter +@AllArgsConstructor @NoArgsConstructor +@EqualsAndHashCode +@Builder(toBuilder = true) public class ResumedDataTemplate { private String prefix; private String lnType; private String lnClass; private String lnInst; + @Builder.Default + @NonNull private DoTypeName doName = new DoTypeName(""); + @Builder.Default + @NonNull private DaTypeName daName = new DaTypeName(""); public static ResumedDataTemplate copyFrom(ResumedDataTemplate dtt){ @@ -41,27 +44,29 @@ public static ResumedDataTemplate copyFrom(ResumedDataTemplate dtt){ } public boolean isUpdatable(){ - return daName.isDefined() && daName.isUpdatable(); + return daName.isDefined() && daName.isUpdatable(); } @JsonIgnore public String getObjRef(String iedName, String ldInst){ - StringBuilder stringBuilder = new StringBuilder(); //LDName - stringBuilder.append(iedName) - .append(ldInst) - .append("/"); + return iedName + ldInst + "/" + getLNRef(); + } + + @JsonIgnore + public String getLNRef(){ + StringBuilder stringBuilder = new StringBuilder(); if(TLLN0Enum.LLN_0.value().equals(lnClass)){ stringBuilder.append(TLLN0Enum.LLN_0.value()); } else { stringBuilder.append(prefix) - .append(lnClass) - .append(lnInst); + .append(lnClass) + .append(lnInst); } stringBuilder.append('.') - .append(getDoRef()) - .append('.') - .append(getDaRef()); + .append(getDoRef()) + .append('.') + .append(getDaRef()); return stringBuilder.toString(); } @@ -120,13 +125,19 @@ public List getBdaNames(){ return List.of(daName.getStructNames().toArray(new String[0])); } - public void addStructName(String structName, Class cls){ - if(cls.equals(DaTypeName.class) && isDaNameDefined()) { - daName.addStructName(structName); - } else if(cls.equals(DoTypeName.class) && isDoNameDefined()) { + public void addDoStructName(String structName){ + if(isDoNameDefined()) { doName.addStructName(structName); } else { - throw new IllegalArgumentException("Cannot add Struct name for undefined data type"); + throw new IllegalArgumentException("DO name must be defined before adding DO StructName"); + } + } + + public void addDaStructName(String structName){ + if(isDaNameDefined()) { + daName.addStructName(structName); + } else { + throw new IllegalArgumentException("DA name must be defined before adding DA StructName"); } } @@ -190,7 +201,6 @@ public void setValImport(boolean valImport) { } } - public boolean isValImport(){ return daName.isValImport(); } 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 index 71da6181b..f8266ac0f 100644 --- 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 @@ -306,7 +306,6 @@ public static Set getDAI(SCL scd, String iedName, String ld ); return lDeviceAdapter.getDAI(rDtt, updatable); - } public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedDataTemplate rDtt) throws ScdException { diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapter.java index eaad69172..9e2c796af 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapter.java @@ -12,7 +12,10 @@ import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; import org.lfenergy.compas.sct.commons.exception.ScdException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; @Slf4j @@ -197,45 +200,33 @@ public void check(DaTypeName daTypeName) throws ScdException { * Each Resumed Data Type Template is instantiated from a reference resumed Data Type. * @apiNote This method doesn't check relationship between DO/SDO and DA. Check should be done by caller * @param rootRDTT reference Resumed Data Type Template used to build the list - * @param visitedBDA a cache to stored visited SDO * @param filter filter for DO/SDO and DA/BDA * @return list of completed Resumed Data Type Templates beginning from this DoType (Do or SDO). */ - public List getResumedDTTs(ResumedDataTemplate rootRDTT, - Set visitedBDA, ResumedDataTemplate filter) { + public List getResumedDTTs(ResumedDataTemplate rootRDTT, ResumedDataTemplate filter) { - List resumedDataTemplates = new ArrayList<>(); + List resultRDTTs = new ArrayList<>(); for(TBDA bda : currentElem.getBDA()){ if(filter != null && filter.isDaNameDefined() && !filter.getBdaNames().contains(bda.getName())){ continue; } - rootRDTT.setBType(bda.getBType().value()); + ResumedDataTemplate currentRDTT = ResumedDataTemplate.copyFrom(rootRDTT); + currentRDTT.setBType(bda.getBType().value()); if(bda.getBType() == TPredefinedBasicTypeEnum.STRUCT) { - if(visitedBDA.contains(bda.getType())) { - continue; - } - - DATypeAdapter daTypeAdapter = parentAdapter.getDATypeAdapterById(bda.getType()).orElse(null); - visitedBDA.add(bda.getType()); - rootRDTT.addStructName(bda.getName(),DaTypeName.class); - if(daTypeAdapter != null){ - List resumedDataTemplateList = daTypeAdapter.getResumedDTTs( - rootRDTT,visitedBDA,filter - ); - resumedDataTemplates.addAll(resumedDataTemplateList); - } + currentRDTT.addDaStructName(bda.getName()); + parentAdapter.getDATypeAdapterById(bda.getType()).ifPresent( + daTypeAdapter -> resultRDTTs.addAll(daTypeAdapter.getResumedDTTs(currentRDTT, filter))); } else { - ResumedDataTemplate resumedDataTemplate = ResumedDataTemplate.copyFrom(rootRDTT); - resumedDataTemplate.addStructName(bda.getName(),DaTypeName.class); - resumedDataTemplate.setType(bda.getType()); - resumedDataTemplate.getDaName().setValImport(bda.isValImport()); - resumedDataTemplate.getDaName().addDaiValues(bda.getVal()); - resumedDataTemplates.add(resumedDataTemplate); + currentRDTT.addDaStructName(bda.getName()); + currentRDTT.setType(bda.getType()); + currentRDTT.getDaName().setValImport(bda.isValImport()); + currentRDTT.getDaName().addDaiValues(bda.getVal()); + resultRDTTs.add(currentRDTT); } } - return resumedDataTemplates; + return resultRDTTs; } public Optional getDATypeAdapterByBdaName(String name) { diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapter.java index 931757ae7..84c3a7166 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapter.java @@ -317,65 +317,60 @@ public TPredefinedCDCEnum getCdc() { * return a list of Resumed Data Type Templates beginning from this DoType (Do or SDO). * @apiNote This method doesn't check relationship between DO/SDO and DA. Check should be done by caller * @param rootRDTT reference Resumed Data Type Template used to build the list - * @param visitedSdo a cache to stored visited SDO * @param filter filter for DO/SDO and DA/BDA * @return list of Resumed Data Type Templates beginning from this DoType (Do or SDO) */ - public List getResumedDTTs(ResumedDataTemplate rootRDTT, - Set visitedSdo, ResumedDataTemplate filter) { - - List rDtts = new ArrayList<>(); + public List getResumedDTTs(ResumedDataTemplate rootRDTT, ResumedDataTemplate filter) { + List resultRDTTs = new ArrayList<>(); for(TUnNaming tUnNaming: currentElem.getSDOOrDA()){ if(tUnNaming.getClass() == TDA.class){ TDA tda = (TDA)tUnNaming; - if(filter.isDaNameDefined() && - !filter.getDaName().getName().equals(tda.getName()) ){ - // filter out - continue; - } - - rootRDTT.getDaName().setName(tda.getName()); - rootRDTT.getDaName().setFc(tda.getFc()); - rootRDTT.getDaName().setBType(tda.getBType()); - if(tda.getBType() == TPredefinedBasicTypeEnum.STRUCT){ - DATypeAdapter daTypeAdapter = parentAdapter.getDATypeAdapterById(tda.getType()).orElse(null); - if(daTypeAdapter != null){ - // get list of Resumed Data Type Templates beginning from this DAType - List resumedDataTemplateList = daTypeAdapter.getResumedDTTs( - rootRDTT,new HashSet<>(), filter - ); - rDtts.addAll(resumedDataTemplateList); - } - } else { - ResumedDataTemplate resumedDataTemplate = ResumedDataTemplate.copyFrom(rootRDTT); - resumedDataTemplate.getDaName().setType(tda.getType()); - resumedDataTemplate.getDaName().setValImport(tda.isValImport()); - resumedDataTemplate.setDaiValues(tda.getVal()); - rDtts.add(resumedDataTemplate); - } + resultRDTTs.addAll(getResumedDTTsOfDA(rootRDTT, filter, tda)); } else { TSDO tsdo = (TSDO)tUnNaming; - if((filter != null && - !filter.getSdoNames().isEmpty() && - !filter.getSdoNames().contains(tsdo.getName())) || - visitedSdo.contains(tsdo.getType())){ + if(excludedByFilter(filter, tsdo)){ continue; } - ResumedDataTemplate rDtt = ResumedDataTemplate.copyFrom(rootRDTT); - - DOTypeAdapter doTypeAdapter = parentAdapter.getDOTypeAdapterById(tsdo.getType()).orElse(null); - visitedSdo.add(tsdo.getType()); - rDtt.addStructName(tsdo.getName(),DoTypeName.class); - if(doTypeAdapter != null){ - // get list of Resumed Data Type Templates beginning from this SDO - List localRDtts = doTypeAdapter.getResumedDTTs(rDtt,visitedSdo, filter); - rDtts.addAll(localRDtts); - } + ResumedDataTemplate currentRDTT = ResumedDataTemplate.copyFrom(rootRDTT); + currentRDTT.addDoStructName(tsdo.getName()); + parentAdapter.getDOTypeAdapterById(tsdo.getType()).ifPresent( + doTypeAdapter -> + resultRDTTs.addAll(doTypeAdapter.getResumedDTTs(currentRDTT, filter))); } } - return rDtts; + return resultRDTTs; } + private List getResumedDTTsOfDA(ResumedDataTemplate rootRDTT, ResumedDataTemplate filter, TDA da){ + if(excludedByFilter(filter, da)){ + return Collections.emptyList(); + } + ResumedDataTemplate currentRDTT = ResumedDataTemplate.copyFrom(rootRDTT); + currentRDTT.getDaName().setName(da.getName()); + currentRDTT.getDaName().setFc(da.getFc()); + currentRDTT.getDaName().setBType(da.getBType()); + if(da.getBType() == TPredefinedBasicTypeEnum.STRUCT){ + return parentAdapter.getDATypeAdapterById(da.getType()) + .map(daTypeAdapter -> daTypeAdapter.getResumedDTTs(currentRDTT, filter)) + .orElse(Collections.emptyList()); + } else { + currentRDTT.getDaName().setType(da.getType()); + currentRDTT.getDaName().setValImport(da.isValImport()); + currentRDTT.setDaiValues(da.getVal()); + return List.of(currentRDTT); + } + } + + private boolean excludedByFilter(ResumedDataTemplate filter, TDA da) { + return filter != null && filter.isDaNameDefined() && + !filter.getDaName().getName().equals(da.getName()); + } + + private boolean excludedByFilter(ResumedDataTemplate filter, TSDO tsdo) { + return filter != null && + !filter.getSdoNames().isEmpty() && + !filter.getSdoNames().contains(tsdo.getName()); + } public Optional getDOTypeAdapterBySdoName(String name) { Optional opSdo = getSDOByName(name); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapter.java index d3f17e979..48c425c0d 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapter.java @@ -17,7 +17,10 @@ import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; @Slf4j public class LNodeTypeAdapter @@ -101,11 +104,11 @@ public List getResumedDTTs(@NonNull ResumedDataTemplate fil return resumedDataTemplates; } } - ResumedDataTemplate rootResumedRTT = new ResumedDataTemplate(); - rootResumedRTT.setLnType(currentElem.getId()); - rootResumedRTT.setLnClass(filter.getLnClass()); - rootResumedRTT.setLnInst(filter.getLnInst()); - rootResumedRTT.setPrefix(filter.getPrefix()); + ResumedDataTemplate rootRDTT = new ResumedDataTemplate(); + rootRDTT.setLnType(currentElem.getId()); + rootRDTT.setLnClass(filter.getLnClass()); + rootRDTT.setLnInst(filter.getLnInst()); + rootRDTT.setPrefix(filter.getPrefix()); for(TDO tdo : currentElem.getDO()){ if(filter.isDoNameDefined() && @@ -113,16 +116,14 @@ public List getResumedDTTs(@NonNull ResumedDataTemplate fil continue; } - rootResumedRTT.getDoName().setName(tdo.getName()); - DOTypeAdapter doTypeAdapter = parentAdapter.getDOTypeAdapterById(tdo.getType()).orElse(null); - if(doTypeAdapter != null){ - rootResumedRTT.getDoName().setCdc(doTypeAdapter.getCdc()); - List rDTTList = doTypeAdapter.getResumedDTTs( - rootResumedRTT,new HashSet<>(), filter - ); - resumedDataTemplates.addAll(rDTTList); - } // else this should never happen or the scd won't be built in the first place and we'd never be here - // may be use an assert here to enforce constrain + parentAdapter.getDOTypeAdapterById(tdo.getType()).ifPresent( + doTypeAdapter -> { + ResumedDataTemplate currentRDTT = ResumedDataTemplate.copyFrom(rootRDTT); + currentRDTT.getDoName().setName(tdo.getName()); + currentRDTT.getDoName().setCdc(doTypeAdapter.getCdc()); + resumedDataTemplates.addAll(doTypeAdapter.getResumedDTTs(currentRDTT, filter)); + } + ); // else this should never happen or the scd won't be built in the first place and we'd never be here } return resumedDataTemplates; } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractLNAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractLNAdapter.java index 8da50b079..8ce8570ce 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractLNAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractLNAdapter.java @@ -7,34 +7,8 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.lfenergy.compas.scl2007b4.model.LN0; -import org.lfenergy.compas.scl2007b4.model.TAnyLN; -import org.lfenergy.compas.scl2007b4.model.TControl; -import org.lfenergy.compas.scl2007b4.model.TDOI; -import org.lfenergy.compas.scl2007b4.model.TDataSet; -import org.lfenergy.compas.scl2007b4.model.TExtRef; -import org.lfenergy.compas.scl2007b4.model.TFCDA; -import org.lfenergy.compas.scl2007b4.model.TFCEnum; -import org.lfenergy.compas.scl2007b4.model.TGSEControl; -import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; -import org.lfenergy.compas.scl2007b4.model.TReportControl; -import org.lfenergy.compas.scl2007b4.model.TSampledValueControl; -import org.lfenergy.compas.scl2007b4.model.TServiceType; -import org.lfenergy.compas.scl2007b4.model.TVal; -import org.lfenergy.compas.sct.commons.dto.ControlBlock; -import org.lfenergy.compas.sct.commons.dto.DaTypeName; -import org.lfenergy.compas.sct.commons.dto.DataSetInfo; -import org.lfenergy.compas.sct.commons.dto.DoTypeName; -import org.lfenergy.compas.sct.commons.dto.ExtRefBindingInfo; -import org.lfenergy.compas.sct.commons.dto.ExtRefInfo; -import org.lfenergy.compas.sct.commons.dto.ExtRefSignalInfo; -import org.lfenergy.compas.sct.commons.dto.ExtRefSourceInfo; -import org.lfenergy.compas.sct.commons.dto.FCDAInfo; -import org.lfenergy.compas.sct.commons.dto.GooseControlBlock; -import org.lfenergy.compas.sct.commons.dto.LNodeMetaData; -import org.lfenergy.compas.sct.commons.dto.ReportControlBlock; -import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; -import org.lfenergy.compas.sct.commons.dto.SMVControlBlock; +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.ObjectReference; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; @@ -43,13 +17,7 @@ import org.lfenergy.compas.sct.commons.scl.dtt.LNodeTypeAdapter; import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; @@ -472,11 +440,11 @@ public TExtRef checkExtRefInfoCoherence(@NonNull ExtRefInfo extRefInfo) throws S /** * Returns a list of resumed DataTypeTemplate for DataAttribute (updatable or not) * @param rDtt reference resumed DataTypeTemplate (used as filter) - * @param updatable true to retrieve updatable DAI, false otherwise + * @param updatableOnly true to retrieve only updatable DAI, false to retrieve all DAI * @return List of resumed DataTypeTemplate for DataAttribute (updatable or not) * @throws ScdException SCD illegal arguments exception */ - public List getDAI(ResumedDataTemplate rDtt, boolean updatable) throws ScdException { + public List getDAI(ResumedDataTemplate rDtt, boolean updatableOnly) throws ScdException { String lnType = currentElem.getLnType(); if(!StringUtils.isBlank(rDtt.getLnType())){ lnType = rDtt.getLnType(); @@ -492,36 +460,48 @@ public List getDAI(ResumedDataTemplate rDtt, boolean updata ); List resumedDTTs = lNodeTypeAdapter.getResumedDTTs(rDtt); - // complete the list by the overridden information in DAI - resumedDTTs = resumedDTTs.stream() - .map(rDTT -> completeResumedDTTFromDAI(rDTT,updatable)) - .filter(rDTT -> !updatable || (rDTT.isUpdatable())) - .collect(Collectors.toList()); - return resumedDTTs; - } + resumedDTTs.forEach(this::overrideAttributesFromDAI); - protected ResumedDataTemplate completeResumedDTTFromDAI(ResumedDataTemplate rDtt, boolean updatable){ - Optional opDaiAdapter = findMatch(rDtt.getDoName(), rDtt.getDaName()); - if(opDaiAdapter.isPresent()) { - AbstractDAIAdapter daiAdapter = (AbstractDAIAdapter) opDaiAdapter.get(); - if(daiAdapter.isValImport() != null) { - rDtt.setValImport(daiAdapter.isValImport()); - } - rDtt.setDaiValues(daiAdapter.getCurrentElem().getVal()); - if (updatable && (daiAdapter.isValImport() == null || daiAdapter.isValImport())) { - boolean isSg = daiAdapter.getCurrentElem().getVal().stream() - .anyMatch(tVal -> tVal.getSGroup() != null && tVal.getSGroup().intValue() > 0); - - if (isSg) { - IEDAdapter iedAdapter = parentAdapter.getParentAdapter(); - rDtt.setValImport(iedAdapter.isSettingConfig(parentAdapter.getInst())); // override - } else if (rDtt.getDaName().getFc() == TFCEnum.SG || rDtt.getDaName().getFc() == TFCEnum.SE) { - log.warn("Inconsistencies in the SCD file (Setting group and DAI FC)!"); - rDtt.setValImport(false); + if (updatableOnly){ + return resumedDTTs.stream().filter(ResumedDataTemplate::isUpdatable).collect(Collectors.toList()); + } else { + return resumedDTTs; + } + } + + protected void overrideAttributesFromDAI(final ResumedDataTemplate rDtt) { + findMatch(rDtt.getDoName(), rDtt.getDaName()) + .map(iDataAdapter -> (AbstractDAIAdapter) iDataAdapter) + .map(AbstractDAIAdapter::getCurrentElem) + .ifPresent(tdai -> { + rDtt.setDaiValues(tdai.getVal()); + if (rDtt.getDaName().getFc() == TFCEnum.SG || rDtt.getDaName().getFc() == TFCEnum.SE) { + boolean isGroup = hasSgGroup(tdai); + if (isGroup) { + rDtt.setValImport(!Boolean.FALSE.equals(tdai.isValImport()) && iedHasConfSG()); + } else { + rDtt.setValImport(false); + log.warn("Inconsistency in the SCD file - DAI {} with fc={} must have a sGroup attribute", + rDtt.getObjRef(getCurrentIED().getName(), parentAdapter.getInst()), rDtt.getDaName().getFc()); + } + } else if (tdai.isValImport() != null) { + rDtt.setValImport(tdai.isValImport()); } - } - } - return rDtt; + }); + } + + private boolean iedHasConfSG() { + IEDAdapter iedAdapter = getCurrentIED(); + return iedAdapter.isSettingConfig(this.parentAdapter.getInst()); + } + + private IEDAdapter getCurrentIED() { + LDeviceAdapter lDeviceAdapter = this.parentAdapter; + return lDeviceAdapter.getParentAdapter(); + } + + private boolean hasSgGroup(TDAI tdai) { + return tdai.getVal().stream().anyMatch(tVal -> tVal.getSGroup() != null && tVal.getSGroup().intValue() > 0); } /** @@ -531,13 +511,13 @@ protected ResumedDataTemplate completeResumedDTTFromDAI(ResumedDataTemplate rDtt * @param daTypeName defined-DA (da.bda1[.bda2...bda_n]) * @return Optional of DAIAdapter for the matched DAI */ - protected Optional findMatch(DoTypeName doTypeName, DaTypeName daTypeName){ + protected Optional findMatch(DoTypeName doTypeName, DaTypeName daTypeName){ DAITracker daiTracker = new DAITracker(this,doTypeName,daTypeName); DAITracker.MatchResult matchResult = daiTracker.search(); if(matchResult != DAITracker.MatchResult.FULL_MATCH){ return Optional.empty(); } - return Optional.of((AbstractDAIAdapter) daiTracker.getBdaiOrDaiAdapter()); + return Optional.of(daiTracker.getBdaiOrDaiAdapter()); } public void updateDAI(@NonNull ResumedDataTemplate rDtt) throws ScdException { @@ -638,10 +618,10 @@ public boolean matches(ObjectReference objRef) { String.format("Corrupted SCD file: Reference to unknown LNodeType(%s)", getLnType()) ) ); - ResumedDataTemplate filter = new ResumedDataTemplate(); - filter.setLnInst(getLNInst()); - filter.setLnClass(getLNClass()); - filter.setLnType(currentElem.getLnType()); + ResumedDataTemplate filter = ResumedDataTemplate.builder() + .lnInst(getLNInst()) + .lnClass(getLNClass()) + .lnType(currentElem.getLnType()).build(); List rDtts = lNodeTypeAdapter.getResumedDTTs(filter); return matchesDataAttributes(dataAttribute) || diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapter.java index fa3d85831..fdfbf6f89 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapter.java @@ -133,17 +133,13 @@ public Set getDAI(ResumedDataTemplate rDtt, boolean updatab } Set resumedDataTemplateSet = new HashSet<>(); - List resumedDataTemplateList; - ResumedDataTemplate filter; for(AbstractLNAdapter lnAdapter : lnAdapters){ - - filter = ResumedDataTemplate.copyFrom(rDtt); + ResumedDataTemplate filter = ResumedDataTemplate.copyFrom(rDtt); filter.setLnClass(lnAdapter.getLNClass()); filter.setLnInst(lnAdapter.getLNInst()); filter.setPrefix(lnAdapter.getPrefix()); filter.setLnType(lnAdapter.getLnType()); - resumedDataTemplateList = lnAdapter.getDAI(filter, updatable); - resumedDataTemplateSet.addAll(resumedDataTemplateList); + resumedDataTemplateSet.addAll(lnAdapter.getDAI(filter, updatable)); } return resumedDataTemplateSet; diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DaTypeNameTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DaTypeNameTest.java index 19f687ac0..bc7ddf010 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DaTypeNameTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DaTypeNameTest.java @@ -6,40 +6,120 @@ import org.junit.jupiter.api.Test; import org.lfenergy.compas.scl2007b4.model.TFCEnum; -import org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum; -import org.lfenergy.compas.scl2007b4.model.TPredefinedCDCEnum; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.junit.jupiter.api.Assertions.*; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDa; class DaTypeNameTest { @Test - void testConstructor(){ - DaTypeName daTypeName = new DaTypeName("da.bda1.bda2"); - daTypeName.setFc(TFCEnum.CF); - daTypeName.setBType(TPredefinedBasicTypeEnum.CHECK); - daTypeName.setType("IfExist_Its_EnumType"); - assertEquals("da",daTypeName.getName()); - assertEquals(TFCEnum.CF,daTypeName.getFc()); - assertThat(daTypeName.getStructNames(), contains("bda1","bda2")); + void testConstructorWithRef() { + // given : nothing + // when + DaTypeName daTypeName = new DaTypeName("da1.bda1.bda2"); + // then + assertThat(daTypeName.getName()).isEqualTo("da1"); + assertThat(daTypeName.getStructNames()).containsExactly("bda1", "bda2"); + assertThat(daTypeName.getDaiValues()).isNotNull().isEmpty(); + } + + @Test + void testConstructorWithRefWhenEmptyStruct() { + // given : nothing + // when + DaTypeName daTypeName = new DaTypeName("da1"); + // then + assertThat(daTypeName.getName()).isEqualTo("da1"); + assertThat(daTypeName.getStructNames()).isNotNull().isEmpty(); + assertThat(daTypeName.getDaiValues()).isNotNull().isEmpty(); + } + + @Test + void testConstructorWithRefWithNullName() { + // given : nothing + // when + DaTypeName daTypeName = new DaTypeName(null); + // then + assertThat(daTypeName.getName()).isEqualTo(""); + assertThat(daTypeName.getStructNames()).isNotNull().isEmpty(); + assertThat(daTypeName.getDaiValues()).isNotNull().isEmpty(); + } + + @Test + void testConstructor2WithRef() { + // given : nothing + // when + DaTypeName daTypeName = new DaTypeName("da1", "bda1.bda2"); + // then + assertThat(daTypeName.getName()).isEqualTo("da1"); + assertThat(daTypeName.getStructNames()).containsExactly("bda1", "bda2"); + assertThat(daTypeName.getDaiValues()).isNotNull().isEmpty(); + } + + @Test + void testConstructor2WithRefWhenEmptyStruct() { + // given : nothing + // when + DaTypeName daTypeName = new DaTypeName("da1", null); + // then + assertThat(daTypeName.getName()).isEqualTo("da1"); + assertThat(daTypeName.getStructNames()).isNotNull().isEmpty(); + assertThat(daTypeName.getDaiValues()).isNotNull().isEmpty(); + } + + @Test + void testConstructor2WithRefWithNullName() { + // given : nothing + // when + DaTypeName daTypeName = new DaTypeName(null, null); + // then + assertThat(daTypeName.getName()).isEqualTo(""); + assertThat(daTypeName.getStructNames()).isNotNull().isEmpty(); + assertThat(daTypeName.getDaiValues()).isNotNull().isEmpty(); + } - DaTypeName daTypeName1 = new DaTypeName("da","bda1.bda2"); - daTypeName1.setFc(TFCEnum.CF); - daTypeName1.setBType(TPredefinedBasicTypeEnum.CHECK); - daTypeName1.setType("IfExist_Its_EnumType"); - assertEquals(daTypeName,daTypeName1); - assertEquals(daTypeName.hashCode(),daTypeName1.hashCode()); + @Test + void testConstructorWithNameAndStructNames() { + // given : nothing + // when + DaTypeName daTypeName = new DaTypeName("da1", "bda1.bda2"); - daTypeName1.setType("toto"); - assertNotEquals(daTypeName,daTypeName1); + // then + assertThat(daTypeName.getName()).isEqualTo("da1"); + assertThat(daTypeName.getStructNames()).containsExactly("bda1", "bda2"); + } - daTypeName1.setBType(TPredefinedBasicTypeEnum.DBPOS); - assertNotEquals(daTypeName,daTypeName1); + @Test + void testEquals() { + // given : nothing + DaTypeName da1 = createDa("da1.bda1.bda2", TFCEnum.CF, true, Map.of(0L, "value")); + DaTypeName da2 = createDa("da1.bda1.bda2", TFCEnum.CF, true, Map.of(0L, "value")); + // when + boolean result = da1.equals(da2); + // then + assertThat(result).isTrue(); + } - daTypeName1.setFc(TFCEnum.BL); - assertNotEquals(daTypeName,daTypeName1); + @Test + void testNotEquals() { + // given : nothing + DaTypeName da1 = createDa("da1.bda1.bda2", TFCEnum.CF, true, Map.of(0L, "value")); + DaTypeName da2 = createDa("da1.bda1.bda2", TFCEnum.DC, true, Map.of(0L, "value")); + // when + boolean result = da1.equals(da2); + // then + assertThat(result).isFalse(); + } + @Test + void testFrom() { + // given : nothing + DaTypeName da1 = createDa("da1.bda1.bda2", TFCEnum.CF, true, Map.of(0L, "value")); + // when + DaTypeName da2 = DaTypeName.from(da1); + // then + assertThat(da2).isEqualTo(da1); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DoTypeNameTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DoTypeNameTest.java index fc3ca897f..4199498b5 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DoTypeNameTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DoTypeNameTest.java @@ -4,30 +4,114 @@ package org.lfenergy.compas.sct.commons.dto; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; import org.junit.jupiter.api.Test; import org.lfenergy.compas.scl2007b4.model.TPredefinedCDCEnum; -import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDo; class DoTypeNameTest { @Test - void testConstructor(){ - DoTypeName doTypeName = new DoTypeName("do.Sdo1.Sdo2"); - doTypeName.setCdc(TPredefinedCDCEnum.WYE); - assertEquals("do",doTypeName.getName()); - assertEquals(TPredefinedCDCEnum.WYE,doTypeName.getCdc()); - assertThat(doTypeName.getStructNames(), contains("Sdo1","Sdo2")); + void testConstructorWithRef() { + // given : nothing + // when + DoTypeName doTypeName = new DoTypeName("do1.bdo1.bdo2"); + // then + assertThat(doTypeName.getName()).isEqualTo("do1"); + assertThat(doTypeName.getStructNames()).containsExactly("bdo1", "bdo2"); + } - DoTypeName doTypeName2 = new DoTypeName("do","Sdo1.Sdo2"); - doTypeName2.setCdc(TPredefinedCDCEnum.WYE); - assertEquals(doTypeName,doTypeName2); - assertEquals(doTypeName.hashCode(),doTypeName2.hashCode()); + @Test + void testConstructorWithRefWhenEmptyStruct() { + // given : nothing + // when + DoTypeName doTypeName = new DoTypeName("do1"); + // then + assertThat(doTypeName.getName()).isEqualTo("do1"); + assertThat(doTypeName.getStructNames()).isNotNull().isEmpty(); + } - doTypeName2.setCdc(TPredefinedCDCEnum.ACD); - assertNotEquals(doTypeName,doTypeName2); + @Test + void testConstructorWithRefWithNullName() { + // given : nothing + // when + DoTypeName doTypeName = new DoTypeName(null); + // then + assertThat(doTypeName.getName()).isEqualTo(""); + assertThat(doTypeName.getStructNames()).isNotNull().isEmpty(); + } + + @Test + void testConstructor2WithRef() { + // given : nothing + // when + DoTypeName doTypeName = new DoTypeName("do1", "bdo1.bdo2"); + // then + assertThat(doTypeName.getName()).isEqualTo("do1"); + assertThat(doTypeName.getStructNames()).containsExactly("bdo1", "bdo2"); + } + + @Test + void testConstructor2WithRefWhenEmptyStruct() { + // given : nothing + // when + DoTypeName doTypeName = new DoTypeName("do1", null); + // then + assertThat(doTypeName.getName()).isEqualTo("do1"); + assertThat(doTypeName.getStructNames()).isNotNull().isEmpty(); + } + + @Test + void testConstructor2WithRefWithNullName() { + // given : nothing + // when + DoTypeName doTypeName = new DoTypeName(null, null); + // then + assertThat(doTypeName.getName()).isEqualTo(""); + assertThat(doTypeName.getStructNames()).isNotNull().isEmpty(); } -} \ No newline at end of file + @Test + void testConstructorWithNameAndStructNames() { + // given : nothing + // when + DoTypeName doTypeName = new DoTypeName("do1", "bdo1.bdo2"); + + // then + assertThat(doTypeName.getName()).isEqualTo("do1"); + assertThat(doTypeName.getStructNames()).containsExactly("bdo1", "bdo2"); + } + + @Test + void testEquals() { + // given : nothing + DoTypeName do1 = createDo("do1.bdo1.bdo2", TPredefinedCDCEnum.DPS); + DoTypeName do2 = createDo("do1.bdo1.bdo2", TPredefinedCDCEnum.DPS); + // when + boolean result = do1.equals(do2); + // then + assertThat(result).isTrue(); + } + + @Test + void testNotEquals() { + // given : nothing + DoTypeName do1 = createDo("do1.bdo1.bdo2", TPredefinedCDCEnum.DPS); + DoTypeName do2 = createDo("do1.bdo1.bdo2", TPredefinedCDCEnum.ACD); + // when + boolean result = do1.equals(do2); + // then + assertThat(result).isFalse(); + } + + @Test + void testFrom() { + // given : nothing + DoTypeName do1 = createDo("do1.bdo1.bdo2", TPredefinedCDCEnum.DPS); + // when + DoTypeName do2 = DoTypeName.from(do1); + // then + assertThat(do2).isEqualTo(do1); + } +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/LNodeDTOTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/LNodeDTOTest.java index 870b3c261..97f8ca1fd 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/LNodeDTOTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/LNodeDTOTest.java @@ -6,14 +6,17 @@ import org.junit.jupiter.api.Test; import org.lfenergy.compas.scl2007b4.model.TExtRef; +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.ied.IEDAdapter; import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; import org.lfenergy.compas.sct.commons.scl.ied.LNAdapter; -import org.mockito.Mockito; import java.util.List; +import java.util.Optional; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; class LNodeDTOTest { @@ -34,7 +37,7 @@ void testConstructor(){ ()-> assertEquals(DTO.LN_TYPE,lNodeDTO.getNodeType()), ()-> assertEquals(DTO.HOLDER_LN_PREFIX,lNodeDTO.getPrefix()) ); - lNodeDTO.addResumedDataTemplate(new ResumedDataTemplate()); + lNodeDTO.addResumedDataTemplate(ResumedDataTemplate.builder().daName(new DaTypeName("da1")).build()); lNodeDTO.addExtRefInfo(new ExtRefInfo()); lNodeDTO.addControlBlock(new ReportControlBlock()); lNodeDTO.addDataSet(new DataSetInfo()); @@ -42,7 +45,7 @@ void testConstructor(){ lNodeDTO.addAllControlBlocks(List.of(new SMVControlBlock())); lNodeDTO.addAllDatSets(List.of(new DataSetInfo())); lNodeDTO.addAllExtRefInfo(List.of(new ExtRefInfo())); - lNodeDTO.addAllResumedDataTemplate(List.of(new ResumedDataTemplate())); + lNodeDTO.addAllResumedDataTemplate(List.of(ResumedDataTemplate.builder().daName(new DaTypeName("da2")).build())); assertEquals(2, lNodeDTO.getExtRefs().size()); assertEquals(2, lNodeDTO.getDatSets().size()); @@ -53,24 +56,30 @@ void testConstructor(){ @Test void testFrom(){ - IEDAdapter iedAdapter = Mockito.mock(IEDAdapter.class); - LDeviceAdapter lDeviceAdapter = Mockito.mock(LDeviceAdapter.class); - Mockito.when(iedAdapter.getName()).thenReturn(DTO.HOLDER_IED_NAME); - Mockito.when(lDeviceAdapter.getInst()).thenReturn(DTO.HOLDER_LD_INST); - Mockito.when(lDeviceAdapter.getParentAdapter()).thenReturn(iedAdapter); - - LNAdapter lnAdapter = Mockito.mock(LNAdapter.class); - Mockito.when(lnAdapter.getParentAdapter()).thenReturn(lDeviceAdapter); - Mockito.when(lnAdapter.getLNClass()).thenReturn(DTO.HOLDER_LN_CLASS); - Mockito.when(lnAdapter.getLNInst()).thenReturn(DTO.HOLDER_LN_INST); - Mockito.when(lnAdapter.getLnType()).thenReturn(DTO.LN_TYPE); - Mockito.when(lnAdapter.getPrefix()).thenReturn(DTO.HOLDER_LN_PREFIX); + IEDAdapter iedAdapter = mock(IEDAdapter.class); + LDeviceAdapter lDeviceAdapter = mock(LDeviceAdapter.class); + when(iedAdapter.getName()).thenReturn(DTO.HOLDER_IED_NAME); + when(lDeviceAdapter.getInst()).thenReturn(DTO.HOLDER_LD_INST); + when(lDeviceAdapter.getParentAdapter()).thenReturn(iedAdapter); + + LNAdapter lnAdapter = mock(LNAdapter.class); + when(lnAdapter.getParentAdapter()).thenReturn(lDeviceAdapter); + when(lnAdapter.getLNClass()).thenReturn(DTO.HOLDER_LN_CLASS); + when(lnAdapter.getLNInst()).thenReturn(DTO.HOLDER_LN_INST); + when(lnAdapter.getLnType()).thenReturn(DTO.LN_TYPE); + when(lnAdapter.getPrefix()).thenReturn(DTO.HOLDER_LN_PREFIX); + + DataTypeTemplateAdapter dataTypeTemplateAdapter = mock(DataTypeTemplateAdapter.class); + when(lnAdapter.getDataTypeTemplateAdapter()).thenReturn(dataTypeTemplateAdapter); + LNodeTypeAdapter lNodeTypeAdapter = mock(LNodeTypeAdapter.class); + when(dataTypeTemplateAdapter.getLNodeTypeAdapterById(any())).thenReturn(Optional.of(lNodeTypeAdapter)); + when(lNodeTypeAdapter.getResumedDTTs(any())).thenReturn(List.of(ResumedDataTemplate.builder().build())); TExtRef extRef = DTO.createExtRef(); - Mockito.when(lnAdapter.getExtRefs(null)).thenReturn(List.of(extRef)); + when(lnAdapter.getExtRefs(null)).thenReturn(List.of(extRef)); LNodeDTO lNodeDTO = LNodeDTO.from(lnAdapter, - new LogicalNodeOptions(true,false,false,false)); + new LogicalNodeOptions(true,true,false,false)); assertNotNull(lNodeDTO); assertAll("LNODE", ()-> assertEquals(DTO.HOLDER_LN_INST,lNodeDTO.getInst()), @@ -86,21 +95,20 @@ void testFrom(){ assertEquals(DTO.HOLDER_LN_CLASS,extRefInfo.getHolderLnClass()); assertEquals(DTO.HOLDER_LN_INST,extRefInfo.getHolderLnInst()); assertEquals(DTO.HOLDER_LN_PREFIX,extRefInfo.getHolderLnPrefix()); - } @Test void testExtractExtRefInfo(){ - LNAdapter lnAdapter = Mockito.mock(LNAdapter.class); - Mockito.when(lnAdapter.getLNClass()).thenReturn(DTO.HOLDER_LN_CLASS); - Mockito.when(lnAdapter.getLNInst()).thenReturn(DTO.HOLDER_LN_INST); - Mockito.when(lnAdapter.getLnType()).thenReturn(DTO.LN_TYPE); - Mockito.when(lnAdapter.getPrefix()).thenReturn(DTO.HOLDER_LN_PREFIX); - Mockito.when(lnAdapter.hasInputs()).thenReturn(true); + LNAdapter lnAdapter = mock(LNAdapter.class); + when(lnAdapter.getLNClass()).thenReturn(DTO.HOLDER_LN_CLASS); + when(lnAdapter.getLNInst()).thenReturn(DTO.HOLDER_LN_INST); + when(lnAdapter.getLnType()).thenReturn(DTO.LN_TYPE); + when(lnAdapter.getPrefix()).thenReturn(DTO.HOLDER_LN_PREFIX); + when(lnAdapter.hasInputs()).thenReturn(true); TExtRef extRef = DTO.createExtRef(); - Mockito.when(lnAdapter.getExtRefs(null)).thenReturn(List.of(extRef)); + when(lnAdapter.getExtRefs(null)).thenReturn(List.of(extRef)); LNodeDTO lNodeDTO = LNodeDTO.extractExtRefInfo(lnAdapter); @@ -113,4 +121,4 @@ void testExtractExtRefInfo(){ ()-> assertEquals(1,lNodeDTO.getExtRefs().size()) ); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplateTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplateTest.java index 28f60e910..385eda9e6 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplateTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplateTest.java @@ -7,6 +7,11 @@ import org.junit.jupiter.api.Test; import org.lfenergy.compas.scl2007b4.model.TFCEnum; import org.lfenergy.compas.scl2007b4.model.TPredefinedCDCEnum; +import org.lfenergy.compas.scl2007b4.model.TVal; + +import java.util.List; +import java.util.Map; + import static org.junit.jupiter.api.Assertions.*; class ResumedDataTemplateTest { @@ -18,6 +23,99 @@ void testGetObjRef(){ String objRef = resumedDataTemplate.getObjRef("IED","LDTM"); assertEquals(expected,objRef); } + + @Test + void testGetObjRefWhenLLN0(){ + // given + ResumedDataTemplate resumedDataTemplate = DTO.createRTT("pre","LLN0","1"); + // when + String objRef = resumedDataTemplate.getObjRef("IED","LDTM"); + // then + assertEquals("IEDLDTM/LLN0.do.sdo1.sdo2.da.bda1.bda2",objRef); + } + + @Test + void testGetDataAttributes(){ + // given + ResumedDataTemplate resumedDataTemplate = DTO.createRTT("pre","lnclass","1"); + // when + String dataAttributes = resumedDataTemplate.getDataAttributes(); + // then + String expected = "do.sdo1.sdo2.da.bda1.bda2"; + assertEquals(expected, dataAttributes); + } + + @Test + void testAddDoStructName(){ + // given + ResumedDataTemplate resumedDataTemplate = DTO.createRTT("pre","lnclass","1"); + resumedDataTemplate.setDaName(new DaTypeName()); + // when + resumedDataTemplate.addDoStructName("added_sdo"); + // then + String expected = "do.sdo1.sdo2.added_sdo"; + assertEquals(expected, resumedDataTemplate.getDoRef()); + } + + @Test + void testAddDoStructNameWhenNoDoName(){ + // given + ResumedDataTemplate resumedDataTemplate = DTO.createRTT("pre","lnclass","1"); + resumedDataTemplate.setDaName(new DaTypeName()); + resumedDataTemplate.setDoName(new DoTypeName()); + // when & then + assertThrows(IllegalArgumentException.class, () -> resumedDataTemplate.addDoStructName("added_sdo")); + } + + @Test + void testAddDaStructName(){ + // given + ResumedDataTemplate resumedDataTemplate = DTO.createRTT("pre","lnclass","1"); + // when + resumedDataTemplate.addDaStructName("added_bda"); + // then + String expected = "da.bda1.bda2.added_bda"; + assertEquals(expected, resumedDataTemplate.getDaRef()); + } + + @Test + void testAddDaStructNameWhenNoDoName(){ + // given + ResumedDataTemplate resumedDataTemplate = DTO.createRTT("pre","lnclass","1"); + resumedDataTemplate.setDaName(new DaTypeName()); + resumedDataTemplate.setDoName(new DoTypeName()); + // when & then + assertThrows(IllegalArgumentException.class, () -> resumedDataTemplate.addDaStructName("added_sda")); + } + + @Test + void testSetDaiValues(){ + // given + ResumedDataTemplate resumedDataTemplate = DTO.createRTT("pre","lnclass","1"); + TVal val = new TVal(); + val.setValue("test"); + // when + resumedDataTemplate.setDaiValues(List.of(val)); + // then + assertEquals(Map.of(0L, "test"), resumedDataTemplate.getDaName().getDaiValues()); + } + + @Test + void testSetDaiValuesWhenMultipleVal(){ + // given + ResumedDataTemplate resumedDataTemplate = DTO.createRTT("pre","lnclass","1"); + TVal val1 = new TVal(); + val1.setValue("test1"); + val1.setSGroup(0L); + TVal val2 = new TVal(); + val2.setValue("test2"); + val2.setSGroup(1L); + // when + resumedDataTemplate.setDaiValues(List.of(val1, val2)); + // then + assertEquals(Map.of(0L, "test1", 1L, "test2"), resumedDataTemplate.getDaName().getDaiValues()); + } + @Test void testCopyFrom() { ResumedDataTemplate rDtt = DTO.createRTT("pre","lnclass","1"); @@ -58,4 +156,4 @@ void testIsUpdatable(){ rDtt.getDaName().setFc(TFCEnum.BL); assertFalse(rDtt.isUpdatable()); } -} \ No newline at end of file +} 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/scl/SclServiceTest.java index 7dbc3519a..c068214f5 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/scl/SclServiceTest.java @@ -4,6 +4,7 @@ package org.lfenergy.compas.sct.commons.scl; +import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -18,9 +19,12 @@ import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; import java.util.*; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; 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; class SclServiceTest { @@ -320,25 +324,191 @@ private ExtRefSignalInfo createSignalInfo(String pDO, String pDA, String intAddr } @Test - void testGetDAI() throws Exception { + void getDAI_should_return_all_dai() throws Exception { + // given SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); + // when + Set allResults = SclService.getDAI(scd, "IED_NAME1", "LD_INST12", new ResumedDataTemplate(), true); - Set resumedDataTemplates = assertDoesNotThrow( - () -> SclService.getDAI( - scd, "IED_NAME1", "LD_INST12", new ResumedDataTemplate(), 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() throws Exception { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_aggregate_DAI.xml"); + + // when + Set dais = SclService.getDAI(scd, "VirtualBCU", "LDMODEXPF", new ResumedDataTemplate(), false); + + // then + ResumedDataTemplate lln0 = ResumedDataTemplate.builder().prefix("").lnType("lntype1").lnClass("LLN0").lnInst("").build(); + ResumedDataTemplate lln0DoA = lln0.toBuilder().doName(createDo("DoA", TPredefinedCDCEnum.DPL)).build(); + ResumedDataTemplate 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(), + + ResumedDataTemplate.builder().prefix("").lnType("lntype2").lnClass("LPHD").lnInst("0") + .doName(createDo("PhyNam", TPredefinedCDCEnum.DPS)) + .daName(createDa("aDa", TFCEnum.BL, false, Map.of())).build() ); - assertEquals(13, resumedDataTemplates.size()); + } - assertThrows( - ScdException.class, - () -> SclService.getDAI( - scd, "IED_NAME1", "UNKNOWNLD", new ResumedDataTemplate(), true - ) + @Test + void getDAI_when_LDevice_not_found_should_throw_exception() throws Exception { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_1_test.xml"); + + // when & then + assertThrows(ScdException.class, + () -> SclService.getDAI(scd, "IED_NAME1", "UNKNOWNLD", new ResumedDataTemplate(), true)); + } + + @Test + void getDAI_should_filter_updatable_DA() throws Exception { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); + + // when + Set dais = SclService.getDAI(scd, "VirtualBCU", "LDMODEXPF", new ResumedDataTemplate(), true); + + // then + assertThat(dais).isNotNull(); + List resultSimpleDa = dais.stream() + .filter(rdtt -> rdtt.getBdaNames().isEmpty()) // test only simple DA + .map(ResumedDataTemplate::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() throws Exception { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); + + // when + Set dais = SclService.getDAI(scd, "VirtualBCU", "LDMODEXPF", new ResumedDataTemplate(), true); + + // then + assertThat(dais).isNotNull(); + List resultStructDa = dais.stream() + .filter(rdtt -> !rdtt.getBdaNames().isEmpty()) // test only struct DA + .map(ResumedDataTemplate::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() throws Exception { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); + + // when + Set dais = SclService.getDAI(scd, "VirtualBCU", "LDCAP", new ResumedDataTemplate(), true); + + // then + assertThat(dais).isNotNull(); + List resultSimpleDa = dais.stream() + .filter(rdtt -> rdtt.getBdaNames().isEmpty()) // test only simple DA + .map(ResumedDataTemplate::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() throws Exception { + // given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-import-ieds/ied_test_updatable_DAI.xml"); + + // when + Set dais = SclService.getDAI(scd, "VirtualBCU", "LDMOD", new ResumedDataTemplate(), true); + + // then + assertThat(dais) + .isNotNull() + .isEmpty(); + } + @Test void testInitScl() { assertDoesNotThrow( @@ -515,4 +685,4 @@ void testImportSTDElementsInSCD_No_STD_Match() throws Exception { assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, new HashSet<>(), DTO.comMap)); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapterTest.java index b99bf63d2..5f40825a7 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapterTest.java @@ -16,7 +16,6 @@ import org.mockito.Mockito; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -122,9 +121,7 @@ void testGetResumedRTTs() throws Exception { ResumedDataTemplate rootRDtt = new ResumedDataTemplate(); rootRDtt.getDaName().setName("origin"); rootRDtt.getDoName().setName("StrVal"); - var rDtts = daTypeAdapter.getResumedDTTs( - rootRDtt, new HashSet<>(), new ResumedDataTemplate() - ); + List rDtts = daTypeAdapter.getResumedDTTs(rootRDtt, new ResumedDataTemplate()); assertEquals(2,rDtts.size()); } @@ -156,4 +153,4 @@ void addPrivate() throws Exception { daTypeAdapter.addPrivate(tPrivate); assertEquals(2, daTypeAdapter.getCurrentElem().getPrivate().size()); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapterTest.java index 4c4ff8795..843bd9684 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapterTest.java @@ -12,7 +12,6 @@ import org.lfenergy.compas.sct.commons.exception.ScdException; import org.mockito.Mockito; -import java.util.HashSet; import java.util.List; import static org.junit.jupiter.api.Assertions.*; @@ -95,23 +94,36 @@ void testCheckAndCompleteStructData() throws Exception { } @Test - void testGetResumedDTTs() throws Exception { + void testGetResumedDTTs_filter_on_DO() throws Exception { + // given DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT); DOTypeAdapter doTypeAdapter = assertDoesNotThrow(() ->dttAdapter.getDOTypeAdapterById("DO2").get()); ResumedDataTemplate rootRDtt = new ResumedDataTemplate(); rootRDtt.setDoName(new DoTypeName("Op")); ResumedDataTemplate filter = new ResumedDataTemplate(); filter.setDoName(new DoTypeName("Op.res")); - var rDtts = doTypeAdapter.getResumedDTTs( - rootRDtt, new HashSet<>(), filter - ); + + // when + List rDtts = doTypeAdapter.getResumedDTTs(rootRDtt, filter); + + // then assertEquals(2,rDtts.size()); + } + @Test + void testGetResumedDTTs_filter_on_DO_and_DA() throws Exception { + // given + DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT); + DOTypeAdapter doTypeAdapter = assertDoesNotThrow(() ->dttAdapter.getDOTypeAdapterById("DO2").get()); + ResumedDataTemplate rootRDtt = new ResumedDataTemplate(); + rootRDtt.setDoName(new DoTypeName("Op")); + ResumedDataTemplate filter = new ResumedDataTemplate(); filter.setDoName(new DoTypeName("Op.res")); filter.setDaName(new DaTypeName("d")); - rDtts = doTypeAdapter.getResumedDTTs( - rootRDtt, new HashSet<>(), filter - ); + // when + List rDtts = doTypeAdapter.getResumedDTTs(rootRDtt, filter); + + // then assertEquals(1,rDtts.size()); } @@ -159,4 +171,4 @@ void addPrivate() throws Exception { doTypeAdapter.addPrivate(tPrivate); assertEquals(1, doTypeAdapter.getCurrentElem().getPrivate().size()); } -} \ No newline at end of file +} 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 277d8bcf3..5b05181e3 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 @@ -275,7 +275,7 @@ void testFindMatch() throws Exception { LN0Adapter ln0Adapter = lDeviceAdapter.getLN0Adapter(); DoTypeName doTypeName = new DoTypeName("Do.sdo1.d"); DaTypeName daTypeName = new DaTypeName("antRef.bda1.bda2.bda3"); - AbstractDAIAdapter daiAdapter = assertDoesNotThrow(() -> ln0Adapter.findMatch(doTypeName,daTypeName).get()); + AbstractDAIAdapter daiAdapter = (AbstractDAIAdapter) assertDoesNotThrow(() -> ln0Adapter.findMatch(doTypeName,daTypeName).get()); assertEquals("bda3",daiAdapter.getCurrentElem().getName()); assertEquals("Completed-diff",daiAdapter.getCurrentElem().getVal().get(0).getValue()); @@ -325,4 +325,4 @@ void addPrivate() { lnAdapter.addPrivate(tPrivate); assertEquals(1, lnAdapter.getCurrentElem().getPrivate().size()); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/DataTypeUtils.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/DataTypeUtils.java new file mode 100644 index 000000000..72b5ad47f --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/DataTypeUtils.java @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2021 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.testhelpers; + +import org.lfenergy.compas.scl2007b4.model.TFCEnum; +import org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum; +import org.lfenergy.compas.scl2007b4.model.TPredefinedCDCEnum; +import org.lfenergy.compas.sct.commons.dto.DaTypeName; +import org.lfenergy.compas.sct.commons.dto.DoTypeName; + +import java.util.Map; + +public class DataTypeUtils { + public static DaTypeName createDa(String nameRef, TFCEnum fc, boolean valImport, Map daiValues) { + DaTypeName resultDa = new DaTypeName(nameRef); + resultDa.setFc(fc); + resultDa.setBType(TPredefinedBasicTypeEnum.INT_8); + resultDa.setValImport(valImport); + resultDa.setDaiValues(daiValues); + return resultDa; + } + + public static DoTypeName createDo(String nameRef, TPredefinedCDCEnum cdc) { + DoTypeName resultDo = new DoTypeName(nameRef); + resultDo.setCdc(cdc); + return resultDo; + } + + private DataTypeUtils() { + throw new UnsupportedOperationException("This is a utility class, it should not be instantiated."); + } +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/MarshallerWrapper.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/MarshallerWrapper.java index 11c36035e..92fb85aa0 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/MarshallerWrapper.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/MarshallerWrapper.java @@ -14,7 +14,9 @@ import javax.xml.transform.Result; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; @Slf4j public class MarshallerWrapper { @@ -59,7 +61,7 @@ public T unmarshall(final InputStream xml, Class cls) { return cls.cast(result); } catch (JAXBException exp) { String message = String.format("Error unmarshalling to the Class: %s", exp.getLocalizedMessage()); - log.error(message); + log.error(message, exp); throw new CompasException(CompasErrorCode.UNMARSHAL_ERROR_CODE, message); } } diff --git a/sct-commons/src/test/resources/scl-srv-import-ieds/ied_test_aggregate_DAI.xml b/sct-commons/src/test/resources/scl-srv-import-ieds/ied_test_aggregate_DAI.xml new file mode 100644 index 000000000..895a91c85 --- /dev/null +++ b/sct-commons/src/test/resources/scl-srv-import-ieds/ied_test_aggregate_DAI.xml @@ -0,0 +1,87 @@ + + + + + +
+ + + + + + + + + + 1 + + + + + + + + + + 1 + + + + + + + + + + VDF + + + + + + + + + + + + + + + + + + + + 0 + + + + + 0 + + + + + + + + + + + + + + + 0 + + + + + 0 + + + + + + diff --git a/sct-commons/src/test/resources/scl-srv-import-ieds/ied_test_updatable_DAI.xml b/sct-commons/src/test/resources/scl-srv-import-ieds/ied_test_updatable_DAI.xml new file mode 100644 index 000000000..e44309a2f --- /dev/null +++ b/sct-commons/src/test/resources/scl-srv-import-ieds/ied_test_updatable_DAI.xml @@ -0,0 +1,257 @@ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + + + + + VDF + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6dcdd01f6c844e1d51d3d2cd25b3fc71592e4aff Mon Sep 17 00:00:00 2001 From: massifben <105049157+massifben@users.noreply.github.com> Date: Mon, 4 Jul 2022 12:03:13 +0200 Subject: [PATCH 20/23] [#74] : delete all Control Blocks and Dataset and remove all ExtRef source attributes Signed-off-by: massifben <105049157+massifben@users.noreply.github.com> --- sct-commons/pom.xml | 7 +- .../lfenergy/compas/sct/commons/Utils.java | 86 ++++++------- .../compas/sct/commons/dto/ControlBlock.java | 15 +-- .../compas/sct/commons/dto/DaTypeName.java | 2 +- .../compas/sct/commons/dto/FCDAInfo.java | 5 +- .../sct/commons/dto/GooseControlBlock.java | 9 +- .../sct/commons/dto/SMVControlBlock.java | 12 +- .../compas/sct/commons/scl/SclService.java | 23 +++- .../scl/dtt/AbstractDataAttributeAdapter.java | 28 ++--- .../commons/scl/ied/AbstractDAIAdapter.java | 13 +- .../commons/scl/ied/AbstractLNAdapter.java | 48 +++++--- .../sct/commons/scl/ied/LN0Adapter.java | 7 ++ .../main/resources/binding_configuration.xjb | 12 ++ .../compas/sct/commons/UtilsTest.java | 114 ++++++++++++++++++ .../sct/commons/scl/SclServiceTest.java | 67 +++++++++- .../sct/commons/scl/ied/DOIAdapterTest.java | 6 +- .../scl-with-control-blocks.xml | 55 +++++++++ 17 files changed, 370 insertions(+), 139 deletions(-) create mode 100644 sct-commons/src/main/resources/binding_configuration.xjb create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/UtilsTest.java create mode 100644 sct-commons/src/test/resources/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index 1eaf5f727..451d86799 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -32,7 +32,7 @@ org.apache.commons commons-lang3 - 3.11 + 3.12.0 jakarta.xml.bind @@ -196,6 +196,9 @@ ${project.build.directory}/xsd/SCL2007B4/SCL.xsd ${project.build.directory}/xsd/SCL_CoMPAS.xsd + + ${project.basedir}/src/main/resources/binding_configuration.xjb + org.lfenergy.compas.scl2007b4.model true @@ -214,4 +217,4 @@ - \ No newline at end of file + diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/Utils.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/Utils.java index 91703eb81..8ca0711d2 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/Utils.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/Utils.java @@ -6,78 +6,68 @@ import lombok.extern.slf4j.Slf4j; -import java.lang.reflect.Field; +import java.util.Objects; +import java.util.function.Function; +import java.util.function.Predicate; @Slf4j public class Utils { + public static final String LEAVING_PREFIX = "<<< Leaving: ::"; + public static final String ENTERING_PREFIX = ">>> Entering: ::"; + private Utils() { throw new IllegalStateException("Utils class"); } - public static String entering(){ - return ">>> " + - "Entering: " + - "-::" + - getMethodName(); + public static String entering() { + return ENTERING_PREFIX + + getMethodName(); } - public static String leaving(Long startTime){ - if(startTime == null || startTime <= 0){ - return leaving(); + public static String leaving(Long startTime) { + if (startTime == null || startTime <= 0) { + return LEAVING_PREFIX + + getMethodName(); } - return "<<< " + - "Leaving: " + - "-::" + - getMethodName() + - " - Timer duration: " + - (System.nanoTime() - startTime) / Math.pow(10, 9) + - " sec."; + return LEAVING_PREFIX + + getMethodName() + + " - Timer duration: " + + (System.nanoTime() - startTime) / Math.pow(10, 9) + + " sec."; } - public static String getMethodName() { + private static String getMethodName() { try { return (new Throwable()).getStackTrace()[2].getMethodName(); - } catch (Exception e){ + } catch (Exception e) { return "-"; } } - public static String leaving(){ - return "<<< " + - "Leaving: " + - "::" + - getMethodName(); + public static String leaving() { + return LEAVING_PREFIX + + getMethodName(); } /** - * Returns the first {@link Field} in the hierarchy for the specified name + * Test if two fields with primitive values are equals or are both not set. + * @param o1 object to compare + * @param o2 object to compare + * @param isSet predicate that returns if fields is set + * @param getValue getter that return the unboxed field + * @return true if both fields are set and are equals, or if both fields are not set. False otherwise. */ - public static Field getField(Class clazz, String name) { - Field field = null; - while (clazz != null && field == null) { - try { - field = clazz.getDeclaredField(name); - } catch (Exception e) { - log.error("Cannot find field name {}", name, e); - } - clazz = clazz.getSuperclass(); + public static boolean equalsOrNotSet(T o1, T o2, Predicate isSet, Function getValue) { + Objects.requireNonNull(o1); + Objects.requireNonNull(o2); + if (!isSet.test(o1)){ + return !isSet.test(o2); } - return field; - } - - /** - * Sets {@code value} to the first {@link Field} in the {@code object} hierarchy, for the specified name - */ - public static void setField(Object object, String fieldName, Object value) { - try { - Field field = getField(object.getClass(), fieldName); - if(field != null){ - field.setAccessible(true); - field.set(object, value); - } - } catch (Exception e) { - log.error("Cannot nullify {} : ",fieldName, e); + if (!isSet.test(o2)){ + return false; } + return Objects.equals(getValue.apply(o1), getValue.apply(o2)); } + } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlock.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlock.java index 5d3352fdc..bf7112460 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlock.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlock.java @@ -7,14 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.lfenergy.compas.scl2007b4.model.TClientLN; -import org.lfenergy.compas.scl2007b4.model.TControl; -import org.lfenergy.compas.scl2007b4.model.TControlWithIEDName; -import org.lfenergy.compas.scl2007b4.model.TPredefinedTypeOfSecurityEnum; -import org.lfenergy.compas.scl2007b4.model.TServiceSettingsNoDynEnum; -import org.lfenergy.compas.scl2007b4.model.TServiceType; -import org.lfenergy.compas.scl2007b4.model.TServices; -import org.lfenergy.compas.sct.commons.Utils; +import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; @@ -79,14 +72,12 @@ public void validateDestination(SclRootAdapter sclRootAdapter) throws ScdExcepti ) ) ); - if(!iedName.getLnClass().isEmpty()) { + if (iedName.isSetLnClass() && !iedName.getLnClass().isEmpty()) { try { lDeviceAdapter.getLNAdapter(iedName.getLnClass().get(0), iedName.getLnInst(), iedName.getPrefix()); - } catch (ScdException e){ + } catch (ScdException e) { throw new ScdException("Control block destination: " + e.getMessage()); } - } else { - Utils.setField(iedName,"lnClass",null); } } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DaTypeName.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DaTypeName.java index ce5166612..a775c1e0e 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DaTypeName.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DaTypeName.java @@ -75,7 +75,7 @@ public void addDaiValues(List vals) { } public void addDaiValue(TVal val) { - if(val.getSGroup() == null){ + if(!val.isSetSGroup()){ daiValues.put(0L,val.getValue()); } else { daiValues.put(val.getSGroup(), val.getValue()); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/FCDAInfo.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/FCDAInfo.java index e62d3c3d7..de23eb520 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/FCDAInfo.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/FCDAInfo.java @@ -39,10 +39,9 @@ public FCDAInfo(String dataSet, TFCDA tfcda) { lnInst = tfcda.getLnInst(); doName = new DoTypeName(tfcda.getDoName()); daName = new DaTypeName(tfcda.getDaName()); - ix = tfcda.getIx(); + ix = tfcda.isSetIx() ? tfcda.getIx() : null; } - @JsonIgnore public TFCDA getFCDA(){ TFCDA tfcda = new TFCDA(); @@ -75,4 +74,4 @@ public TFCDA getFCDA(){ public boolean isValid() { return doName != null && doName.isDefined(); } -} \ No newline at end of file +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/GooseControlBlock.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/GooseControlBlock.java index d1d447ba1..ad683442c 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/GooseControlBlock.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/GooseControlBlock.java @@ -7,12 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.lfenergy.compas.scl2007b4.model.TGSEControl; -import org.lfenergy.compas.scl2007b4.model.TMcSecurity; -import org.lfenergy.compas.scl2007b4.model.TPredefinedTypeOfSecurityEnum; -import org.lfenergy.compas.scl2007b4.model.TProtocol; -import org.lfenergy.compas.scl2007b4.model.TServiceType; -import org.lfenergy.compas.scl2007b4.model.TServices; +import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.exception.ScdException; @@ -27,7 +22,7 @@ public GooseControlBlock(TGSEControl tgseControl) { super(); this.id = tgseControl.getAppID(); this.name = tgseControl.getName(); - if(tgseControl.getConfRev() != null) { + if(tgseControl.isSetConfRev()) { this.confRev = tgseControl.getConfRev(); } this.desc = tgseControl.getDesc(); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SMVControlBlock.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SMVControlBlock.java index 51c2469ff..13abc6425 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SMVControlBlock.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SMVControlBlock.java @@ -7,13 +7,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import org.lfenergy.compas.scl2007b4.model.TMcSecurity; -import org.lfenergy.compas.scl2007b4.model.TPredefinedTypeOfSecurityEnum; -import org.lfenergy.compas.scl2007b4.model.TProtocol; -import org.lfenergy.compas.scl2007b4.model.TSampledValueControl; -import org.lfenergy.compas.scl2007b4.model.TServiceType; -import org.lfenergy.compas.scl2007b4.model.TServices; -import org.lfenergy.compas.scl2007b4.model.TSmpMod; +import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import java.util.Collections; @@ -36,9 +30,7 @@ public SMVControlBlock(TSampledValueControl tSampledValueControl) { super(); this.id = tSampledValueControl.getSmvID(); this.name = tSampledValueControl.getName(); - if(tSampledValueControl.getConfRev() != null) { - this.confRev = tSampledValueControl.getConfRev(); - } + this.confRev = tSampledValueControl.isSetConfRev() ? tSampledValueControl.getConfRev() : null; this.desc = tSampledValueControl.getDesc(); this.dataSetRef = tSampledValueControl.getDatSet(); Collections.copy(iedNames, tSampledValueControl.getIEDName()); 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 index f8266ac0f..f352ec16b 100644 --- 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 @@ -20,10 +20,7 @@ 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.ied.AbstractLNAdapter; -import org.lfenergy.compas.sct.commons.scl.ied.DAITracker; -import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; -import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; +import org.lfenergy.compas.sct.commons.scl.ied.*; import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter; @@ -514,4 +511,22 @@ private static Optional getCompasICDHeader(TPrivate tPrivate) return tCompasICDHeader.map(JAXBElement::getValue); } + public static void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final SCL scl) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scl); + List lDeviceAdapters = sclRootAdapter.getIEDAdapters().stream() + .map(IEDAdapter::getLDeviceAdapters).flatMap(List::stream).collect(Collectors.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); + } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/AbstractDataAttributeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/AbstractDataAttributeAdapter.java index e3e29e5b5..016217710 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/AbstractDataAttributeAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/AbstractDataAttributeAdapter.java @@ -5,11 +5,7 @@ package org.lfenergy.compas.sct.commons.scl.dtt; import lombok.Getter; -import org.lfenergy.compas.scl2007b4.model.TAbstractDataAttribute; -import org.lfenergy.compas.scl2007b4.model.TDA; -import org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum; -import org.lfenergy.compas.scl2007b4.model.TProtNs; -import org.lfenergy.compas.scl2007b4.model.TVal; +import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.Utils; import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.exception.ScdException; @@ -48,7 +44,6 @@ public Optional getDATypeAdapter() { public boolean hasSameContentAs(T data) { - final String countField = "count"; if(!Objects.equals(getName(),data.getName()) || !Objects.equals(getBType(),data.getBType()) || !Objects.equals(getType(),data.getType()) @@ -67,19 +62,11 @@ public boolean hasSameContentAs(T data) { return false; } } - if(!Objects.equals(currentElem.getCount(),data.getCount())){ - if(currentElem.getCount().isEmpty()){ - Utils.setField(currentElem,countField,null); - } - if(data.getCount().isEmpty()){ - Utils.setField(data,countField,null); - } - return false ; - } else if(currentElem.getCount().isEmpty()){ - Utils.setField(currentElem,countField,null); - Utils.setField(data,countField,null); + if (!Utils.equalsOrNotSet(currentElem, data, TAbstractDataAttribute::isSetCount, TAbstractDataAttribute::getCount)){ + return false; } + if((getBType() == TPredefinedBasicTypeEnum.ENUM || getBType() == TPredefinedBasicTypeEnum.STRUCT) && !Objects.equals(getType(),data.getType())) { @@ -87,10 +74,9 @@ public boolean hasSameContentAs(T data) { } for(TVal prdVal : data.getVal()){ - boolean hasSameVal = currentElem.getVal().stream() - .anyMatch(rcvVal -> rcvVal.getValue().equals(prdVal.getValue()) && - Objects.equals(rcvVal.getSGroup(), prdVal.getSGroup())); - if(!hasSameVal) { + if(currentElem.isSetVal() && currentElem.getVal().stream() + .noneMatch(rcvVal -> rcvVal.getValue().equals(prdVal.getValue()) && + Utils.equalsOrNotSet(rcvVal, prdVal, TVal::isSetSGroup, TVal::getSGroup))) { return false; } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractDAIAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractDAIAdapter.java index 6b5c30754..3e4c3144e 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractDAIAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractDAIAdapter.java @@ -30,8 +30,9 @@ public S getDataAdapterByName(String sName) throws Scd public void setValImport(boolean b){ currentElem.setValImport(b); } + public Boolean isValImport(){ - return currentElem.isValImport(); + return currentElem.isSetValImport() ? currentElem.isValImport() : null; } public AbstractDAIAdapter update(Map daiValues) throws ScdException { @@ -46,16 +47,16 @@ public AbstractDAIAdapter update(Map } public void update(Long sGroup, String val) throws ScdException { - if(currentElem.isValImport() != null && !currentElem.isValImport()){ + if(currentElem.isSetValImport() && !currentElem.isValImport()){ String msg = String.format( "DAI(%s) cannot be updated : valImport(false)",currentElem.getName() ); throw new ScdException(msg); } - Stream tValStream = currentElem.getVal().stream() ; - if(sGroup != 0){ - Optional tVal = tValStream.filter(tValElem -> tValElem.getSGroup() != null && - tValElem.getSGroup().equals(sGroup)) + Stream tValStream = currentElem.getVal().stream(); + if (sGroup != null && sGroup != 0) { + Optional tVal = tValStream.filter(tValElem -> tValElem.isSetSGroup() && + sGroup.equals(tValElem.getSGroup())) .findFirst(); if(tVal.isPresent()){ tVal.get().setValue(val); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractLNAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractLNAdapter.java index 8ce8570ce..ff38c0e1b 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractLNAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/AbstractLNAdapter.java @@ -16,7 +16,6 @@ import org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter; import org.lfenergy.compas.sct.commons.scl.dtt.LNodeTypeAdapter; -import java.lang.reflect.Field; import java.util.*; import java.util.stream.Collectors; @@ -98,6 +97,10 @@ public String getLnType(){ return currentElem.getLnType(); } + public List getExtRefs() { + return getExtRefs(null); + } + public List getExtRefs(ExtRefSignalInfo filter) { if(!hasInputs()){ return new ArrayList<>(); @@ -194,20 +197,7 @@ protected void updateExtRefBindingInfo(TExtRef extRef, ExtRefInfo extRefInfo) { extRef.setPrefix(bindingInfo.getPrefix()); // invalid source info - extRef.setSrcCBName(null); - extRef.setSrcLDInst(null); - extRef.setSrcPrefix(null); - extRef.setSrcLNInst(null); - // the JAXB don't provide setter for srcLNClass - // SCL XSD doesn't accept empty srcLNClass list - // No choice here but to do reflection - try { - Field f = extRef.getClass().getDeclaredField("srcLNClass"); - f.setAccessible(true); - f.set(extRef,null); - } catch ( Exception e) { - log.error("Cannot nullify srcLNClass:", e); - } + removeExtRefSourceBinding(extRef); isSrcReset = true; } // @@ -478,13 +468,13 @@ protected void overrideAttributesFromDAI(final ResumedDataTemplate rDtt) { if (rDtt.getDaName().getFc() == TFCEnum.SG || rDtt.getDaName().getFc() == TFCEnum.SE) { boolean isGroup = hasSgGroup(tdai); if (isGroup) { - rDtt.setValImport(!Boolean.FALSE.equals(tdai.isValImport()) && iedHasConfSG()); + rDtt.setValImport((!tdai.isSetValImport() || tdai.isValImport()) && iedHasConfSG()); } else { rDtt.setValImport(false); log.warn("Inconsistency in the SCD file - DAI {} with fc={} must have a sGroup attribute", rDtt.getObjRef(getCurrentIED().getName(), parentAdapter.getInst()), rDtt.getDaName().getFc()); } - } else if (tdai.isValImport() != null) { + } else if (tdai.isSetValImport()) { rDtt.setValImport(tdai.isValImport()); } }); @@ -501,7 +491,7 @@ private IEDAdapter getCurrentIED() { } private boolean hasSgGroup(TDAI tdai) { - return tdai.getVal().stream().anyMatch(tVal -> tVal.getSGroup() != null && tVal.getSGroup().intValue() > 0); + return tdai.getVal().stream().anyMatch(tVal -> tVal.isSetSGroup() && tVal.getSGroup() > 0); } /** @@ -672,8 +662,28 @@ public Map getDAIValues(ResumedDataTemplate rDtt) { } Map res = new HashMap<>(); - tVals.forEach( tVal -> res.put(tVal.getSGroup(),tVal.getValue())); + tVals.forEach( tVal -> res.put( + tVal.isSetSGroup() ? tVal.getSGroup() : 0L, tVal.getValue()) + ); return res; } + + public void removeAllControlBlocksAndDatasets() { + currentElem.unsetReportControl(); + currentElem.unsetLogControl(); + currentElem.unsetDataSet(); + } + + public void removeAllExtRefSourceBindings() { + getExtRefs().forEach(this::removeExtRefSourceBinding); + } + + private void removeExtRefSourceBinding(final TExtRef tExtRef){ + tExtRef.setSrcCBName(null); + tExtRef.setSrcLDInst(null); + tExtRef.setSrcPrefix(null); + tExtRef.setSrcLNInst(null); + tExtRef.unsetSrcLNClass(); + } } 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 a269255d2..4d86941a4 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 @@ -51,4 +51,11 @@ protected boolean matchesDataAttributes(String dataAttribute){ currentElem.getSampledValueControl().stream().anyMatch(smp -> smp.getName().equals(dataAttribute)) || currentElem.getGSEControl().stream().anyMatch(gse -> gse.getName().equals(dataAttribute)); } + + @Override + public void removeAllControlBlocksAndDatasets() { + super.removeAllControlBlocksAndDatasets(); + currentElem.unsetGSEControl(); + currentElem.unsetSampledValueControl(); + } } diff --git a/sct-commons/src/main/resources/binding_configuration.xjb b/sct-commons/src/main/resources/binding_configuration.xjb new file mode 100644 index 000000000..6ecd6bf93 --- /dev/null +++ b/sct-commons/src/main/resources/binding_configuration.xjb @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/UtilsTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/UtilsTest.java new file mode 100644 index 000000000..243b2f36b --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/UtilsTest.java @@ -0,0 +1,114 @@ +// SPDX-FileCopyrightText: 2021 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons; + +import org.junit.jupiter.api.Test; + +import java.util.NoSuchElementException; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.*; + +class UtilsTest { + + @Test + void entering_should_return_text() { + // Given : method name + // When + String entering = Utils.entering(); + // Then + assertEquals(">>> Entering: ::entering_should_return_text", entering); + } + + @Test + void leaving_should_return_text() { + // Given : method name + // When + String leaving = Utils.leaving(); + // Then + assertEquals("<<< Leaving: ::leaving_should_return_text", leaving); + } + + @Test + void leaving_should_return_text_with_time() { + // Given : method name + // When + String leaving = Utils.leaving(System.nanoTime()); + // Then + assertTrue(leaving.matches("<<< Leaving: ::leaving_should_return_text_with_time - Timer duration: .* sec."), leaving); + } + + @Test + void leaving_should_return_text_with_invalid_time() { + // Given : method name + // When + String leaving = Utils.leaving(-1L); + // Then + assertEquals("<<< Leaving: ::leaving_should_return_text_with_invalid_time", leaving); + } + + @Test + void equalsOrNotSet_should_return_true_when_both_values_are_not_set() { + // Given + Optional object1= Optional.empty(); + Optional object2 = Optional.empty(); + // When + boolean result1 = Utils.equalsOrNotSet(object1, object2, Optional::isPresent, Optional::get); + boolean result2 = Utils.equalsOrNotSet(object2, object1, Optional::isPresent, Optional::get); + // Then + assertTrue(result1); + assertTrue(result2); + } + + @Test + void equalsOrNotSet_should_return_true_when_both_values_are_set_and_equal() { + // Given + Optional object1= Optional.of(1L); + Optional object2 = Optional.of(1L); + // When + boolean result1 = Utils.equalsOrNotSet(object1, object2, Optional::isPresent, Optional::get); + boolean result2 = Utils.equalsOrNotSet(object2, object1, Optional::isPresent, Optional::get); + // Then + assertTrue(result1); + assertTrue(result2); + } + + @Test + void equalsOrNotSet_should_return_false_when_both_values_are_set_but_differ() { + // Given + Optional object1= Optional.of(1L); + Optional object2 = Optional.of(2L); + // When + boolean result1 = Utils.equalsOrNotSet(object1, object2, Optional::isPresent, Optional::get); + boolean result2 = Utils.equalsOrNotSet(object2, object1, Optional::isPresent, Optional::get); + // Then + assertFalse(result1); + assertFalse(result2); + } + + @Test + void equalsOrNotSet_should_return_false_when_one_is_set_and_the_other_is_not() { + // Given + Optional object1= Optional.of(1L); + Optional object2 = Optional.empty(); + // When + boolean result1 = Utils.equalsOrNotSet(object1, object2, Optional::isPresent, Optional::get); + boolean result2 = Utils.equalsOrNotSet(object2, object1, Optional::isPresent, Optional::get); + // Then + assertFalse(result1); + assertFalse(result2); + } + + @Test + void equalsOrNotSet_should_throw_exception_when_value_is_null_and_isSet_is_misleading() { + // Given + Optional object1= Optional.of(1L); + Optional object2 = Optional.empty(); + // When & Then + assertThrows(NoSuchElementException.class, () -> Utils.equalsOrNotSet(object1, object2, o -> true, Optional::get)); + assertThrows(NoSuchElementException.class, () -> Utils.equalsOrNotSet(object2, object1, o -> true, Optional::get)); + } + +} 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/scl/SclServiceTest.java index c068214f5..6c437dfc9 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/scl/SclServiceTest.java @@ -12,9 +12,7 @@ import org.lfenergy.compas.sct.commons.CommonConstants; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; -import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; -import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; -import org.lfenergy.compas.sct.commons.scl.ied.LN0Adapter; +import org.lfenergy.compas.sct.commons.scl.ied.*; import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; @@ -685,4 +683,67 @@ void testImportSTDElementsInSCD_No_STD_Match() throws Exception { assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, new HashSet<>(), DTO.comMap)); } + + @Test + void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_Dataset_on_ln0() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml"); + // When + SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); + // Then + SclRootAdapter scdRootAdapter = new SclRootAdapter(scl); + List lDevices = scdRootAdapter.getIEDAdapters().stream().map(IEDAdapter::getLDeviceAdapters) + .flatMap(List::stream).collect(Collectors.toList()); + List ln0s = lDevices.stream().map(LDeviceAdapter::getLN0Adapter).map(LN0Adapter::getCurrentElem).collect(Collectors.toList()); + assertThat(ln0s) + .isNotEmpty() + .noneMatch(TAnyLN::isSetDataSet) + .noneMatch(TAnyLN::isSetLogControl) + .noneMatch(TAnyLN::isSetReportControl) + .noneMatch(LN0::isSetGSEControl) + .noneMatch(LN0::isSetSampledValueControl); + } + + @Test + void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_Dataset_on_ln() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml"); + // When + SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); + // Then + SclRootAdapter scdRootAdapter = new SclRootAdapter(scl); + List lDevices = scdRootAdapter.getIEDAdapters().stream().map(IEDAdapter::getLDeviceAdapters) + .flatMap(List::stream).collect(Collectors.toList()); + List lns = lDevices.stream().map(LDeviceAdapter::getLNAdapters).flatMap(List::stream) + .map(LNAdapter::getCurrentElem).collect(Collectors.toList()); + assertThat(lns) + .isNotEmpty() + .noneMatch(TAnyLN::isSetDataSet) + .noneMatch(TAnyLN::isSetLogControl) + .noneMatch(TAnyLN::isSetReportControl); + } + + @Test + void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_srcXXX_attributes_on_ExtRef() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml"); + // When + SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); + // Then + SclRootAdapter scdRootAdapter = new SclRootAdapter(scl); + List extRefs = scdRootAdapter + .getIEDAdapters().stream() + .map(IEDAdapter::getLDeviceAdapters).flatMap(List::stream) + .map(LDeviceAdapter::getLN0Adapter) + .map(AbstractLNAdapter::getExtRefs).flatMap(List::stream) + .collect(Collectors.toList()); + assertThat(extRefs) + .isNotEmpty() + .noneMatch(TExtRef::isSetSrcLDInst) + .noneMatch(TExtRef::isSetSrcPrefix) + .noneMatch(TExtRef::isSetSrcLNInst) + .noneMatch(TExtRef::isSetSrcCBName) + .noneMatch(TExtRef::isSetSrcLNClass); + } + } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/DOIAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/DOIAdapterTest.java index 4fbad1dba..d848c7199 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/DOIAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/DOIAdapterTest.java @@ -77,7 +77,7 @@ void testInnerDAIAdapterTestUpdateWithMapAsArg(){ assertDoesNotThrow(() -> daiAdapter.update(vals)); assertFalse(daiAdapter.getCurrentElem().getVal().isEmpty()); TVal tVal = daiAdapter.getCurrentElem().getVal().get(0); - assertNull(tVal.getSGroup()); + assertFalse(tVal.isSetSGroup()); final Map vals2 = new HashMap<>(); vals2.put(1L,TOTO); @@ -85,7 +85,7 @@ void testInnerDAIAdapterTestUpdateWithMapAsArg(){ assertDoesNotThrow(() -> daiAdapter.update(vals2)); assertFalse(daiAdapter.getCurrentElem().getVal().isEmpty()); tVal = daiAdapter.getCurrentElem().getVal().get(0); - assertNull(tVal.getSGroup()); + assertFalse(tVal.isSetSGroup()); } @Test @@ -156,4 +156,4 @@ void addPrivate() { daiAdapter.addPrivate(tPrivate); assertEquals(1, daiAdapter.getCurrentElem().getPrivate().size()); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/resources/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml b/sct-commons/src/test/resources/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml new file mode 100644 index 000000000..59e826a1d --- /dev/null +++ b/sct-commons/src/test/resources/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml @@ -0,0 +1,55 @@ + + + + + + + SSD + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From d58e0cb39096a5ecb4eaf1f17ed6b9d7d83d829d Mon Sep 17 00:00:00 2001 From: Samir Romdhani Date: Tue, 9 Aug 2022 14:41:22 +0200 Subject: [PATCH 21/23] fix error marshalling SCL after automatic scd creation call (#127) [#126] fix importSTDElementsInSCD when copying Compas ICDHeader and add assertIsMarshallable to tests Signed-off-by: samirromdhani Signed-off-by: massifben <105049157+massifben@users.noreply.github.com> Co-authored-by: samirromdhani Co-authored-by: massifben <105049157+massifben@users.noreply.github.com> --- .../SclAutomationServiceTest.java | 19 ++++++- .../compas/sct/commons/scl/SclService.java | 31 ++++++------ .../sct/commons/scl/SclRootAdapterTest.java | 11 ++-- .../sct/commons/scl/SclServiceTest.java | 50 +++++++++++-------- .../sct/commons/scl/ied/IEDAdapterTest.java | 8 +-- .../testhelpers/SclTestMarshaller.java | 7 +++ 6 files changed, 78 insertions(+), 48 deletions(-) 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 6aecfd219..84e413104 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 @@ -17,6 +17,7 @@ import java.util.Set; import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; class SclAutomationServiceTest { @@ -30,20 +31,25 @@ void init(){ } @Test - void createSCD() throws Exception { + void createSCD_should_return_generatedSCD() throws Exception { + // 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 SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std)); + // Then assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); assertNull(expectedSCD.getCurrentElem().getHeader().getHistory()); assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size()); assertEquals(1, expectedSCD.getCurrentElem().getIED().size()); assertNotNull(expectedSCD.getCurrentElem().getDataTypeTemplates()); assertEquals(2, expectedSCD.getCurrentElem().getCommunication().getSubNetwork().size()); + assertIsMarshallable(expectedSCD.getCurrentElem()); } @Test void createSCD_With_HItem() throws Exception { + // Given HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); historyItem.setWhat("what"); historyItem.setWho("me"); @@ -53,14 +59,18 @@ void createSCD_With_HItem() throws Exception { SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml"); SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml"); + // When SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std1, std2, std3)); + // Then assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); assertEquals(1 ,expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size()); + assertIsMarshallable(expectedSCD.getCurrentElem()); } @Test void createSCD_With_HItems() throws Exception { + // Given HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); historyItem.setWhat("what"); historyItem.setWho("me"); @@ -74,17 +84,22 @@ void createSCD_With_HItems() throws Exception { SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml"); SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml"); + // When SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO,Set.of(std1, std2, std3)); + // Then assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); assertEquals(1, expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); assertEquals("what", expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().get(0).getWhat()); + assertIsMarshallable(expectedSCD.getCurrentElem()); } @Test void createSCD_SSD_Without_Substation() throws Exception { + // Given SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml"); + // When & Then assertThrows(ScdException.class, () -> SclAutomationService.createSCD(ssd, headerDTO, new HashSet<>()) ); } -} \ No newline at end of file +} 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 index f352ec16b..bcd2cb5b6 100644 --- 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 @@ -412,7 +412,7 @@ public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdR for (Map.Entry entry : mapIEDNameAndPrivate.entrySet()) { String iedName = entry.getKey(); TPrivate tPrivate = entry.getValue(); - String icdSysVerUuid = getCompasICDHeader(tPrivate).map(TCompasICDHeader::getICDSystemVersionUUID).orElseThrow( + String icdSysVerUuid = getCompasICDHeaderValue(tPrivate).map(TCompasICDHeader::getICDSystemVersionUUID).orElseThrow( () -> new ScdException(ICD_SYSTEM_VERSION_UUID + " is not present in COMPAS-ICDHeader in LNode") ); @@ -446,10 +446,10 @@ private static void checkSTDCorrespondanceWithLNodeCompasICDHeader(Map new ScdException(CommonConstants.COMPAS_ICDHEADER + "not found in LNode Private ")); return iedCompasICDHeader.getIEDType().equals(scdCompasICDHeader.getIEDType()) && iedCompasICDHeader.getICDSystemVersionUUID().equals(scdCompasICDHeader.getICDSystemVersionUUID()) @@ -495,20 +495,21 @@ private static boolean comparePrivateCompasICDHeaders(TPrivate iedPrivate, TPriv } private static void copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(TPrivate stdPrivate, TPrivate lNodePrivate) throws ScdException { - TCompasICDHeader lNodeCompasICDHeader = getCompasICDHeader(lNodePrivate).orElseThrow( + JAXBElement lNodeCompasICDHeader = getCompasICDHeader(lNodePrivate).orElseThrow( () -> new ScdException(CommonConstants.COMPAS_ICDHEADER + "not found in LNode Private ")); stdPrivate.getContent().clear(); stdPrivate.getContent().add(lNodeCompasICDHeader); - } - private static Optional getCompasICDHeader(TPrivate tPrivate) { - Optional> tCompasICDHeader = !tPrivate.getType().equals(CommonConstants.COMPAS_ICDHEADER) ? Optional.empty() : + private static Optional> getCompasICDHeader(TPrivate tPrivate) { + return !tPrivate.getType().equals(CommonConstants.COMPAS_ICDHEADER) ? Optional.empty() : tPrivate.getContent().stream() .filter(JAXBElement.class::isInstance) .map(o -> (JAXBElement) o) .findFirst(); - return tCompasICDHeader.map(JAXBElement::getValue); + } + private static Optional getCompasICDHeaderValue(TPrivate tPrivate) { + return getCompasICDHeader(tPrivate).map(JAXBElement::getValue); } public static void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final SCL scl) { diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapterTest.java index c35d252e1..f83ab071b 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapterTest.java @@ -9,12 +9,12 @@ import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.exception.ScdException; -import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; import java.util.concurrent.atomic.AtomicReference; import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; @Slf4j class SclRootAdapterTest { @@ -34,6 +34,7 @@ void testConstruction() { assertEquals(SclRootAdapter.RELEASE,sclRootAdapter.get().getSclRelease()); assertEquals(SclRootAdapter.VERSION,sclRootAdapter.get().getSclVersion()); assertEquals(SclRootAdapter.REVISION,sclRootAdapter.get().getSclRevision()); + assertIsMarshallable(sclRootAdapter.get().getCurrentElem()); assertThrows(IllegalArgumentException.class, () -> new SclRootAdapter(new SCL())); } @@ -50,10 +51,7 @@ void addIED() throws Exception { assertDoesNotThrow(() -> sclRootAdapter.addIED(icd1, "IED_NAME1")); assertThrows(ScdException.class, () -> sclRootAdapter.addIED(icd1, "IED_NAME1")); assertDoesNotThrow(() -> sclRootAdapter.addIED(icd2, "IED_NAME2")); - - MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); - System.out.println(marshallerWrapper.marshall(sclRootAdapter.getCurrentElem())); - + assertIsMarshallable(scd); } @Test @@ -66,5 +64,6 @@ void addPrivate() throws Exception { assertTrue(sclRootAdapter.getCurrentElem().getPrivate().isEmpty()); sclRootAdapter.addPrivate(tPrivate); assertEquals(1, sclRootAdapter.getCurrentElem().getPrivate().size()); + assertIsMarshallable(scd); } -} \ No newline at end of file +} 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/scl/SclServiceTest.java index 6c437dfc9..ce5dc93e9 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/scl/SclServiceTest.java @@ -13,7 +13,6 @@ import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; 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 java.util.*; @@ -23,6 +22,7 @@ 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.SclTestMarshaller.assertIsMarshallable; class SclServiceTest { @@ -43,6 +43,7 @@ void testAddHistoryItem() throws ScdException { assertEquals("why", tHitem.getWhy()); assertEquals(SclRootAdapter.REVISION, tHitem.getRevision()); assertEquals(SclRootAdapter.VERSION, tHitem.getVersion()); + assertIsMarshallable(scd); } @Test @@ -57,8 +58,7 @@ void testAddIED() throws Exception { assertEquals("IED_NAME1", iedAdapter.getName()); assertNotNull(sclRootAdapter.getCurrentElem().getDataTypeTemplates()); - MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); - System.out.println(marshallerWrapper.marshall(scd)); + assertIsMarshallable(scd); } @Test @@ -79,8 +79,7 @@ void testAddSubnetworks() throws Exception { subNetworkDTO.addConnectedAP(connectedApDTO); assertDoesNotThrow(() -> SclService.addSubnetworks(scd, Set.of(subNetworkDTO), Optional.of(icd)).get()); - MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); - System.out.println(marshallerWrapper.marshall(scd)); + assertIsMarshallable(scd); } @Test @@ -93,8 +92,7 @@ void testAddSubnetworksWithoutCommunicationTagInIcd() throws Exception { assertDoesNotThrow(() -> SclService.addIED(scd, "IED_NAME1", icd)); assertDoesNotThrow(() -> SclService.addSubnetworks(scd, new HashSet<>(), Optional.of(icd))); - MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); - String marshalledScd = marshallerWrapper.marshall(scd); + String marshalledScd = assertIsMarshallable(scd); assertThat(marshalledScd).doesNotContain(" subNetworkDTOSet = new HashSet<>(SclService.getSubnetwork(icd)); assertDoesNotThrow(() -> SclService.addSubnetworks(scd, subNetworkDTOSet, Optional.of(icd)).get()); - MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); - String marshalledScd = marshallerWrapper.marshall(scd); + String marshalledScd = assertIsMarshallable(scd); assertThat(marshalledScd).contains("
", "PhysConn"); } @@ -127,8 +124,7 @@ void testAddSubnetworksWithoutImportingIcdAddressAndPhysConn() throws Exception Set subNetworkDTOSet = new HashSet<>(SclService.getSubnetwork(icd)); assertDoesNotThrow(() -> SclService.addSubnetworks(scd, subNetworkDTOSet, Optional.empty()).get()); - MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); - String marshalledScd = marshallerWrapper.marshall(scd); + String marshalledScd = assertIsMarshallable(scd); assertThat(marshalledScd).doesNotContain("
", "PhysConn"); } @@ -240,6 +236,7 @@ void testUpdateExtRefBinders() throws Exception { ScdException.class, () -> SclService.updateExtRefBinders(scd, extRefInfo) ); + assertIsMarshallable(scd); } @Test @@ -509,17 +506,19 @@ void getDAI_should_filter_updatable_DA_with_sGroup_Val_without_ConfSg() throws E @Test void testInitScl() { - assertDoesNotThrow( - () -> SclService.initScl(Optional.empty(), "hVersion", "hRevision") + SclRootAdapter sclRootAdapter = assertDoesNotThrow( + () -> SclService.initScl(Optional.empty(), "hVersion", "hRevision") ); + assertIsMarshallable(sclRootAdapter.getCurrentElem()); } @Test void testInitScl_With_hId_shouldNotThrowError() { UUID hid = UUID.randomUUID(); - assertDoesNotThrow( - () -> SclService.initScl(Optional.of(hid), "hVersion", "hRevision") + SclRootAdapter sclRootAdapter = assertDoesNotThrow( + () -> SclService.initScl(Optional.of(hid), "hVersion", "hRevision") ); + assertIsMarshallable(sclRootAdapter.getCurrentElem()); } @Test @@ -530,6 +529,7 @@ void testInitScl_Create_Private_SCL_FILETYPE() { ); assertThat(rootAdapter.getCurrentElem().getPrivate()).isNotEmpty(); assertThat(rootAdapter.getCurrentElem().getPrivate().get(0).getType()).isEqualTo(CommonConstants.COMPAS_SCL_FILE_TYPE); + assertIsMarshallable(rootAdapter.getCurrentElem()); } @Test @@ -541,8 +541,7 @@ void testUpdateHeader() { UUID hId = UUID.fromString(sclRootAdapter.getHeaderAdapter().getHeaderId()); HeaderDTO headerDTO = DTO.createHeaderDTO(hId); SclService.updateHeader(sclRootAdapter.getCurrentElem(), headerDTO); - SclService.updateHeader(sclRootAdapter.getCurrentElem(), headerDTO); - + assertIsMarshallable(sclRootAdapter.getCurrentElem()); } @Test @@ -564,7 +563,7 @@ void testUpdateDAI() throws Exception { tVal.setValue("newValue"); rDtt.setDaiValues(List.of(tVal)); assertDoesNotThrow(() -> SclService.updateDAI(scd, "IED_NAME", "LD_INS1", rDtt)); - + assertIsMarshallable(scd); } @Test @@ -586,6 +585,7 @@ void testAddSubstation_Check_SSD_Validity(String ssdFileName) throws Exception { assertThrows(ScdException.class, () -> SclService.addSubstation(scd, ssd)); + assertIsMarshallable(scd); } @Test @@ -598,6 +598,7 @@ void testAddSubstation_SCD_Without_Substation() throws Exception { assertNotEquals(scdRootAdapter, expectedScdAdapter); assertEquals(expectedScdAdapter.getCurrentElem().getSubstation(), ssdRootAdapter.getCurrentElem().getSubstation()); + assertIsMarshallable(scd); } @Test @@ -607,6 +608,7 @@ void testAddSubstation_SCD_With_Different_Substation_Name() throws Exception { assertThrows(ScdException.class, () -> SclService.addSubstation(scd, ssd)); + assertIsMarshallable(scd); } @Test @@ -622,6 +624,7 @@ void testAddSubstation_SCD_With_Substation() throws Exception { assertNotEquals(scdRootAdapter, expectedScdAdapter); assertEquals(expectedTSubstation.getName(), tSubstation.getName()); assertEquals(expectedTSubstation.getVoltageLevel().size(), tSubstation.getVoltageLevel().size()); + assertIsMarshallable(scd); } @Test @@ -635,6 +638,7 @@ void testImportSTDElementsInSCD() throws Exception { assertThat(expectedScdAdapter.getCurrentElem().getIED()).hasSize(1); assertThat(expectedScdAdapter.getCurrentElem().getDataTypeTemplates()).hasNoNullFieldsOrProperties(); assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork()).hasSize(2); + assertIsMarshallable(scd); } @Test @@ -652,6 +656,7 @@ void testImportSTDElementsInSCD_with_Multiple_STD() throws Exception { assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork()).hasSize(2); assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork().get(0).getConnectedAP()).hasSizeBetween(1,3); assertThat(expectedScdAdapter.getCurrentElem().getCommunication().getSubNetwork().get(1).getConnectedAP()).hasSizeBetween(1,3); + assertIsMarshallable(scd); } @Test @@ -662,7 +667,7 @@ void testImportSTDElementsInSCD_Several_STD_Match_Compas_ICDHeader() throws Exce SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); assertThrows(ScdException.class, () -> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std, std1), DTO.comMap)); - + assertIsMarshallable(scd); } @Test @@ -672,7 +677,7 @@ void testImportSTDElementsInSCD_Compas_ICDHeader_Not_Match() throws Exception { SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, Set.of(std), DTO.comMap)); - + assertIsMarshallable(scd); } @Test @@ -681,7 +686,7 @@ void testImportSTDElementsInSCD_No_STD_Match() throws Exception { SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); assertThrows(ScdException.class, ()-> SclService.importSTDElementsInSCD(scdRootAdapter, new HashSet<>(), DTO.comMap)); - + assertIsMarshallable(scd); } @Test @@ -702,6 +707,7 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_D .noneMatch(TAnyLN::isSetReportControl) .noneMatch(LN0::isSetGSEControl) .noneMatch(LN0::isSetSampledValueControl); + assertIsMarshallable(scl); } @Test @@ -721,6 +727,7 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_D .noneMatch(TAnyLN::isSetDataSet) .noneMatch(TAnyLN::isSetLogControl) .noneMatch(TAnyLN::isSetReportControl); + assertIsMarshallable(scl); } @Test @@ -744,6 +751,7 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_srcXXX_attributes_o .noneMatch(TExtRef::isSetSrcLNInst) .noneMatch(TExtRef::isSetSrcCBName) .noneMatch(TExtRef::isSetSrcLNClass); + assertIsMarshallable(scl); } } 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 320ad9886..b75e19ff6 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 @@ -13,7 +13,6 @@ import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.ObjectReference; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; -import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; import org.mockito.Mockito; @@ -22,6 +21,7 @@ import java.util.Map; import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; class IEDAdapterTest { @@ -155,8 +155,7 @@ void testCreateDataSet() throws Exception { dataSetInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); assertDoesNotThrow(() -> iAdapter.createDataSet(dataSetInfo)); - MarshallerWrapper marshallerWrapper = SclTestMarshaller.createWrapper(); - System.out.println(marshallerWrapper.marshall(scd)); + assertIsMarshallable(scd); } @Test @@ -227,6 +226,7 @@ void createControlBlock() throws Exception { controlBlock.setHolderIEDName("IED_NAME"); controlBlock.setHolderIEDName("IED_NAME"); controlBlock.setHolderIEDName("IED_NAME"); + assertIsMarshallable(scd); } @Test @@ -244,4 +244,4 @@ void addPrivate() { iAdapter.addPrivate(tPrivate); assertEquals(1, iAdapter.getCurrentElem().getPrivate().size()); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclTestMarshaller.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclTestMarshaller.java index c0fc4850d..98594458b 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclTestMarshaller.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclTestMarshaller.java @@ -7,6 +7,8 @@ import org.apache.commons.io.IOUtils; import org.lfenergy.compas.scl2007b4.model.SCL; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; + public class SclTestMarshaller { public static SCL getSCLFromFile(String filename) throws Exception { @@ -15,6 +17,11 @@ public static SCL getSCLFromFile(String filename) throws Exception { return marshallerWrapper.unmarshall(rawXml,SCL.class); } + public static String assertIsMarshallable(SCL scl) { + MarshallerWrapper marshallerWrapper = createWrapper(); + return assertDoesNotThrow(() -> marshallerWrapper.marshall(scl)); + } + public static MarshallerWrapper createWrapper() { return MarshallerWrapper.builder() .withProperties("classpath:scl_schema.yml") From e8964e26d93bd420f68248229894123099faa0a6 Mon Sep 17 00:00:00 2001 From: SaintierFr <99645240+SaintierFr@users.noreply.github.com> Date: Wed, 17 Aug 2022 11:21:56 +0200 Subject: [PATCH 22/23] Feat #120: Update compas-sct POM with newer compas-core (and scl-extension) version. Definition in the top project pom to be easily updatable in the future. (#121) Signed-off-by: SaintierFr <99645240+SaintierFr@users.noreply.github.com> Signed-off-by: SaintierFr <99645240+SaintierFr@users.noreply.github.com> --- pom.xml | 24 +++++++++++++++++++++++- sct-app/pom.xml | 3 --- sct-commons/pom.xml | 3 +-- sct-data/pom.xml | 1 - 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 769f09f99..691f13b8b 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,8 @@ sct-coverage/** ../sct-coverage/target/site/jacoco-aggregate/jacoco.xml ${basedir}/${aggregate.report.dir} + 0.9.1 + 0.0.4 @@ -71,7 +73,12 @@ org.lfenergy.compas.core scl-extension - 0.8.0 + ${scl-extension.version} + + + org.lfenergy.compas.xsd + compas-scl-xsd + ${compas-scl-xsd.version} ch.qos.logback @@ -104,6 +111,16 @@ + + org.lfenergy.compas.xsd + compas-scl-xsd + ${compas-scl-xsd.version} + + + org.lfenergy.compas.core + scl-extension + ${scl-extension.version} + org.apache.maven.plugins maven-compiler-plugin @@ -119,6 +136,11 @@ maven-surefire-plugin 2.22.2 + + org.apache.maven.plugins + maven-jar-plugin + 3.2.2 + diff --git a/sct-app/pom.xml b/sct-app/pom.xml index d8a715842..1c1c23a22 100644 --- a/sct-app/pom.xml +++ b/sct-app/pom.xml @@ -13,7 +13,6 @@ local-SNAPSHOT - org.lfenergy.compas sct-app local-SNAPSHOT SCT-APP @@ -112,12 +111,10 @@ org.lfenergy.compas.xsd compas-scl-xsd - 0.0.4 org.lfenergy.compas.core scl-extension - 0.8.0 ${project.build.directory} diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index 451d86799..7581c4e90 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -112,6 +112,7 @@ test + @@ -166,12 +167,10 @@ org.lfenergy.compas.xsd compas-scl-xsd - 0.0.4 org.lfenergy.compas.core scl-extension - 0.8.0 ${project.build.directory} diff --git a/sct-data/pom.xml b/sct-data/pom.xml index 91e9382af..c585ba219 100644 --- a/sct-data/pom.xml +++ b/sct-data/pom.xml @@ -14,7 +14,6 @@ local-SNAPSHOT - org.lfenergy.compas sct-data local-SNAPSHOT SCT-DATA From 09acc2b0237cbe6c6ba5fb8e25b790b4119a2d2a Mon Sep 17 00:00:00 2001 From: massifben <105049157+massifben@users.noreply.github.com> Date: Wed, 17 Aug 2022 11:31:48 +0200 Subject: [PATCH 23/23] [#67] : update LNode iedName (#124) * [#67] : update /Substation/VoltageLevel/Bay/Function/LNode.iedName Signed-off-by: massifben <105049157+massifben@users.noreply.github.com> * [#67] : take comments into account Signed-off-by: massifben <105049157+massifben@users.noreply.github.com> * [#67] : add XPath in error message Signed-off-by: massifben <105049157+massifben@users.noreply.github.com> Signed-off-by: massifben <105049157+massifben@users.noreply.github.com> --- .../compas/sct/app/SclAutomationService.java | 3 +- .../compas/sct/commons/CommonConstants.java | 31 --- .../compas/sct/commons/dto/ControlBlock.java | 2 +- .../compas/sct/commons/dto/LDeviceDTO.java | 4 +- .../compas/sct/commons/dto/LNodeDTO.java | 2 +- .../sct/commons/exception/ScdException.java | 5 +- .../sct/commons/scl/PrivateService.java | 133 +++++++++ .../sct/commons/scl/SclElementAdapter.java | 19 +- .../sct/commons/scl/SclRootAdapter.java | 4 +- .../compas/sct/commons/scl/SclService.java | 134 ++-------- .../sct/commons/scl/SubstationService.java | 89 ++++++ .../commons/scl/com/CommunicationAdapter.java | 6 - .../commons/scl/com/ConnectedAPAdapter.java | 6 - .../commons/scl/com/SubNetworkAdapter.java | 6 - .../scl/dtt/AbstractDataAttributeAdapter.java | 2 +- .../compas/sct/commons/scl/dtt/DAAdapter.java | 5 - .../sct/commons/scl/dtt/DATypeAdapter.java | 14 +- .../compas/sct/commons/scl/dtt/DOAdapter.java | 6 - .../sct/commons/scl/dtt/DOTypeAdapter.java | 5 - .../scl/dtt/DataTypeTemplateAdapter.java | 5 - .../sct/commons/scl/dtt/EnumTypeAdapter.java | 5 - .../sct/commons/scl/dtt/LNodeTypeAdapter.java | 6 - .../sct/commons/scl/header/HeaderAdapter.java | 6 - .../sct/commons/scl/ied/DOIAdapter.java | 14 +- .../sct/commons/scl/ied/IEDAdapter.java | 5 - .../sct/commons/scl/ied/LDeviceAdapter.java | 5 - .../sct/commons/scl/ied/LN0Adapter.java | 6 - .../compas/sct/commons/scl/ied/LNAdapter.java | 7 +- .../sct/commons/scl/ied/RootSDIAdapter.java | 10 - .../sct/commons/scl/ied/SDIAdapter.java | 10 - .../sct/commons/scl/sstation/BayAdapter.java | 15 +- .../commons/scl/sstation/FunctionAdapter.java | 79 ++++++ .../commons/scl/sstation/LNodeAdapter.java | 64 +++++ .../scl/sstation/SubstationAdapter.java | 17 +- .../scl/sstation/VoltageLevelAdapter.java | 18 +- .../sct/commons/util/CommonConstants.java | 18 ++ .../compas/sct/commons/util/PrivateEnum.java | 57 ++++ .../compas/sct/commons/{ => util}/Utils.java | 25 +- .../sct/commons/CommonConstantsTest.java | 18 -- .../sct/commons/scl/PrivateServiceTest.java | 253 ++++++++++++++++++ .../sct/commons/scl/SclServiceTest.java | 57 +--- .../commons/scl/SubstationServiceTest.java | 195 ++++++++++++++ .../scl/dtt/DataTypeTemplateAdapterTest.java | 4 +- .../commons/scl/header/HeaderAdapterTest.java | 4 +- .../commons/scl/sstation/BayAdapterTest.java | 38 ++- .../scl/sstation/FunctionAdapterTest.java | 109 ++++++++ .../scl/sstation/LNodeAdapterTest.java | 111 ++++++++ .../testhelpers/MarshallerWrapper.java | 2 +- .../testhelpers/SclTestMarshaller.java | 2 +- .../sct/commons/util/CommonConstantsTest.java | 22 ++ .../sct/commons/util/PrivateEnumTest.java | 45 ++++ .../sct/commons/{ => util}/UtilsTest.java | 92 ++++++- .../scd-with-substation-lnode.xml | 31 +++ 53 files changed, 1457 insertions(+), 374 deletions(-) delete mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/PrivateService.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SubstationService.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/FunctionAdapter.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapter.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/CommonConstants.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/PrivateEnum.java rename sct-commons/src/main/java/org/lfenergy/compas/sct/commons/{ => util}/Utils.java (67%) delete mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/CommonConstantsTest.java create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/PrivateServiceTest.java create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SubstationServiceTest.java create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/FunctionAdapterTest.java create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapterTest.java create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/CommonConstantsTest.java create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/PrivateEnumTest.java rename sct-commons/src/test/java/org/lfenergy/compas/sct/commons/{ => util}/UtilsTest.java (54%) create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/scd-with-substation-lnode.xml 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 b8840930a..3abd95ebf 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 @@ -13,6 +13,7 @@ import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.SclService; +import org.lfenergy.compas.sct.commons.scl.SubstationService; import java.util.*; @@ -32,7 +33,7 @@ public static SclRootAdapter createSCD(@NonNull SCL ssd, @NonNull HeaderDTO head HeaderDTO.HistoryItem hItem = headerDTO.getHistoryItems().get(0); SclService.addHistoryItem(scdAdapter.getCurrentElem(), hItem.getWho(), hItem.getWhat(), hItem.getWhy()); } - SclService.addSubstation(scdAdapter.getCurrentElem(), ssd); + SubstationService.addSubstation(scdAdapter.getCurrentElem(), ssd); SclService.importSTDElementsInSCD(scdAdapter, stds, comMap); return scdAdapter; } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java deleted file mode 100644 index 90dcd01b9..000000000 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/CommonConstants.java +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-FileCopyrightText: 2021 RTE FRANCE -// -// SPDX-License-Identifier: Apache-2.0 - -package org.lfenergy.compas.sct.commons; - -public class CommonConstants { - CommonConstants() { - throw new UnsupportedOperationException("CommonConstants class"); - } - - public static final String XML_DEFAULT_NS_PREFIX = "scl"; - public static final String XML_DEFAULT_NS_URI = "http://www.iec.ch/61850/2003/SCL"; - public static final String XML_DEFAULT_XSD_PATH = "classpath:schema/SCL.xsd"; - - public static final String COMPAS_SCL_FILE_TYPE = "COMPAS-SclFileType"; - public static final String SCL_FILE_TYPE = "SclFileType"; - public static final String COMPAS_ICDHEADER = "COMPAS-ICDHeader"; - public static final String ICD_SYSTEM_VERSION_UUID = "ICDSystemVersionUUID"; - public static final String IED_NAME = "IEDName"; - public static final String HEADER_ID = "headerId"; - public static final String HEADER_VERSION = "headerVersion"; - public static final String HEADER_REVISION = "headerRevision"; - public static final String IED_TYPE = "IEDType"; - public static final String VENDOR_NAME = "VendorName"; - public static final String IED_REDUNDANCY = "IEDredundancy"; - public static final String IED_MODEL = "IEDmodel"; - public static final String HW_REV = "hwRev"; - public static final String SW_REV = "swRev"; - -} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlock.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlock.java index bf7112460..ca09a625a 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlock.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ControlBlock.java @@ -72,7 +72,7 @@ public void validateDestination(SclRootAdapter sclRootAdapter) throws ScdExcepti ) ) ); - if (iedName.isSetLnClass() && !iedName.getLnClass().isEmpty()) { + if (iedName.isSetLnClass()) { try { lDeviceAdapter.getLNAdapter(iedName.getLnClass().get(0), iedName.getLnInst(), iedName.getPrefix()); } catch (ScdException e) { diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LDeviceDTO.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LDeviceDTO.java index fbc91364f..22873f50a 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LDeviceDTO.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LDeviceDTO.java @@ -6,12 +6,10 @@ import lombok.Getter; import lombok.NoArgsConstructor; - import lombok.extern.slf4j.Slf4j; -import org.lfenergy.compas.sct.commons.Utils; import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; import org.lfenergy.compas.sct.commons.scl.ied.LNAdapter; - +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.HashSet; import java.util.List; diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LNodeDTO.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LNodeDTO.java index 3892277b9..5cd8707d4 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LNodeDTO.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/LNodeDTO.java @@ -9,12 +9,12 @@ import lombok.extern.slf4j.Slf4j; import org.lfenergy.compas.scl2007b4.model.TAnyLN; import org.lfenergy.compas.scl2007b4.model.TExtRef; -import org.lfenergy.compas.sct.commons.Utils; 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.ied.AbstractLNAdapter; import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; import org.lfenergy.compas.sct.commons.scl.ied.LNAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.HashSet; import java.util.List; diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/exception/ScdException.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/exception/ScdException.java index dcf62624d..5dd039631 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/exception/ScdException.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/exception/ScdException.java @@ -4,7 +4,10 @@ package org.lfenergy.compas.sct.commons.exception; -public class ScdException extends Exception { +/** + * Thrown when SCD is inconsistent + */ +public class ScdException extends RuntimeException { public ScdException(String message) { super(message); } 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/scl/PrivateService.java new file mode 100644 index 000000000..3a8aa96de --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/PrivateService.java @@ -0,0 +1,133 @@ +// SPDX-FileCopyrightText: 2022 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.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.util.PrivateEnum; + +import javax.xml.bind.JAXBElement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +@Slf4j +public final class PrivateService { + + private PrivateService() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } + + private static final ObjectFactory objectFactory = new ObjectFactory(); + + public static List getCompasPrivates(List tPrivates, Class compasClass) throws ScdException { + PrivateEnum privateEnum = PrivateEnum.fromClass(compasClass); + List compasElements = tPrivates.stream().filter(tPrivate -> privateEnum.getPrivateType().equals(tPrivate.getType())) + .map(TAnyContentFromOtherNamespace::getContent).flatMap(List::stream) + .filter(JAXBElement.class::isInstance).map(JAXBElement.class::cast) + .filter(Predicate.not(JAXBElement::isNil)) + .map(JAXBElement::getValue).collect(Collectors.toList()); + + List result = new ArrayList<>(); + for (Object compasElement : compasElements) { + if (compasClass.isInstance(compasElement)) { + result.add(compasClass.cast(compasElement)); + } else { + throw new ScdException(String.format("Private is inconsistent. It has type=%s which expect JAXBElement<%s> content, " + + "but got JAXBElement<%s>", + privateEnum.getPrivateType(), privateEnum.getCompasClass().getName(), compasElement.getClass().getName())); + } + } + return result; + } + + public static List getCompasPrivates(TBaseElement baseElement, Class compasClass) throws ScdException { + if (!baseElement.isSetPrivate()) { + return Collections.emptyList(); + } + return getCompasPrivates(baseElement.getPrivate(), compasClass); + } + + public static Optional getCompasPrivate(TPrivate tPrivate, Class compasClass) throws ScdException { + List compasPrivates = getCompasPrivates(Collections.singletonList(tPrivate), compasClass); + if (compasPrivates.size() > 1) { + throw new ScdException(String.format("Expecting maximum 1 element of type %s in private %s, but got %d", + compasClass.getName(), tPrivate.getType(), compasPrivates.size())); + } + if (compasPrivates.isEmpty()) { + return Optional.empty(); + } + return Optional.of(compasPrivates.get(0)); + } + + public static Optional getCompasICDHeader(TPrivate tPrivate) throws ScdException { + return getCompasPrivate(tPrivate, TCompasICDHeader.class); + } + + public static void removePrivates(TBaseElement baseElement, @NonNull PrivateEnum privateEnum) { + if (baseElement.isSetPrivate()) { + baseElement.getPrivate().removeIf(tPrivate -> privateEnum.getPrivateType().equals(tPrivate.getType())); + if (baseElement.getPrivate().isEmpty()) { + baseElement.unsetPrivate(); + } + } + } + + public static TPrivate createPrivate(TCompasBay compasBay) { + return createPrivate(objectFactory.createBay(compasBay)); + } + + public static TPrivate createPrivate(TCompasCriteria compasCriteria) { + return createPrivate(objectFactory.createCriteria(compasCriteria)); + } + + public static TPrivate createPrivate(TCompasFlow compasFlow) { + return createPrivate(objectFactory.createFlow(compasFlow)); + } + + public static TPrivate createPrivate(TCompasFunction compasFunction) { + return createPrivate(objectFactory.createFunction(compasFunction)); + } + + public static TPrivate createPrivate(TCompasICDHeader compasICDHeader) { + return createPrivate(objectFactory.createICDHeader(compasICDHeader)); + } + + public static TPrivate createPrivate(TCompasLDevice compasLDevice) { + return createPrivate(objectFactory.createLDevice(compasLDevice)); + } + + public static TPrivate createPrivate(TCompasSclFileType compasSclFileType) { + return createPrivate(objectFactory.createSclFileType(compasSclFileType)); + } + + public static TPrivate createPrivate(TCompasSystemVersion compasSystemVersion) { + return createPrivate(objectFactory.createSystemVersion(compasSystemVersion)); + } + + private static TPrivate createPrivate(JAXBElement jaxbElement) { + PrivateEnum privateEnum = PrivateEnum.fromClass(jaxbElement.getDeclaredType()); + TPrivate tPrivate = new TPrivate(); + tPrivate.setType(privateEnum.getPrivateType()); + tPrivate.getContent().add(jaxbElement); + return tPrivate; + } + + + + + + + + + + + + } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclElementAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclElementAdapter.java index 7c09059d7..ad7a44cee 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclElementAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclElementAdapter.java @@ -5,6 +5,7 @@ package org.lfenergy.compas.sct.commons.scl; import lombok.Getter; +import org.lfenergy.compas.scl2007b4.model.TBaseElement; import org.lfenergy.compas.scl2007b4.model.TPrivate; @@ -43,7 +44,21 @@ public final void setCurrentElem(T currentElem){ protected abstract boolean amChildElementRef(); - protected abstract void addPrivate(TPrivate tPrivate); + public void addPrivate(TPrivate tPrivate){ + if (currentElem instanceof TBaseElement){ + ((TBaseElement) currentElem).getPrivate().add(tPrivate); + } else { + throw new UnsupportedOperationException("Not implemented for class " + this.getClass().getName()); + } + } -} + public String getXPath(){ + String parentXpath = (parentAdapter != null) ? parentAdapter.getXPath() : ""; + return parentXpath + "/" + elementXPath(); + } + protected String elementXPath(){ + return String.format("undefined(%s)", currentElem.getClass().getSimpleName()); + } + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapter.java index cf36421d7..c2f7807eb 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapter.java @@ -54,8 +54,8 @@ protected boolean amChildElementRef() { } @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); + protected String elementXPath() { + return "SCL"; } public Short getSclRelease(){ 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 index bcd2cb5b6..c62062162 100644 --- 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 @@ -7,10 +7,7 @@ import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; -import org.lfenergy.compas.scl.extensions.commons.CompasExtensionsConstants; import org.lfenergy.compas.scl2007b4.model.*; -import org.lfenergy.compas.sct.commons.CommonConstants; -import org.lfenergy.compas.sct.commons.Utils; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.com.CommunicationAdapter; @@ -21,22 +18,21 @@ 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.ied.*; -import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; -import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; -import javax.xml.bind.JAXBElement; -import javax.xml.namespace.QName; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; -import static org.lfenergy.compas.sct.commons.CommonConstants.ICD_SYSTEM_VERSION_UUID; +import static org.lfenergy.compas.sct.commons.util.CommonConstants.*; +import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_ICDHEADER; @Slf4j public class SclService { public static final String UNKNOWN_LDEVICE_S_IN_IED_S = "Unknown LDevice (%s) in IED (%s)"; public static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info"; + public static final ObjectFactory objectFactory = new ObjectFactory(); private SclService() { throw new IllegalStateException("SclService class"); @@ -45,20 +41,10 @@ private SclService() { public static SclRootAdapter initScl(Optional hId, String hVersion, String hRevision) throws ScdException { UUID headerId = hId.orElseGet(UUID::randomUUID); SclRootAdapter scdAdapter = new SclRootAdapter(headerId.toString(), hVersion, hRevision); - scdAdapter.addPrivate(initSclFileType()); + scdAdapter.addPrivate(PrivateService.createPrivate(TCompasSclFileType.SCD)); return scdAdapter; } - private static TPrivate initSclFileType() { - TPrivate fileTypePrivate = new TPrivate(); - fileTypePrivate.setType(CommonConstants.COMPAS_SCL_FILE_TYPE); - JAXBElement compasFileType = new JAXBElement<>( - new QName(CompasExtensionsConstants.COMPAS_EXTENSION_NS_URI, CommonConstants.SCL_FILE_TYPE), - TCompasSclFileType.class, TCompasSclFileType.SCD); - fileTypePrivate.getContent().add(compasFileType); - return fileTypePrivate; - } - public static SclRootAdapter addHistoryItem(SCL scd, String who, String what, String why) { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); HeaderAdapter headerAdapter = sclRootAdapter.getHeaderAdapter(); @@ -67,7 +53,6 @@ public static SclRootAdapter addHistoryItem(SCL scd, String who, String what, St } public static SclRootAdapter updateHeader(@NonNull SCL scd, @NonNull HeaderDTO headerDTO) { - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); HeaderAdapter headerAdapter = sclRootAdapter.getHeaderAdapter(); @@ -148,7 +133,6 @@ public static List getExtRefInfo(SCL scd, String iedName, String ldI return lDeviceAdapter.getExtRefInfo(); } - public static List getExtRefBinders(SCL scd, String iedName, String ldInst, String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); @@ -203,10 +187,8 @@ public static void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws Sc abstractLNAdapter.updateExtRefBinders(extRefInfo); } - 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"); @@ -326,7 +308,6 @@ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedData () -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName)) ); - AbstractLNAdapter lnAdapter = AbstractLNAdapter.builder() .withLDeviceAdapter(lDeviceAdapter) .withLnClass(rDtt.getLnClass()) @@ -352,54 +333,6 @@ public static Set> getEnumTypeElements(SCL scd, String idE .collect(Collectors.toSet()); } - public static SclRootAdapter addSubstation(@NonNull SCL scd, @NonNull SCL ssd) throws ScdException { - SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SclRootAdapter ssdRootAdapter = new SclRootAdapter(ssd); - if (scdRootAdapter.getCurrentElem().getSubstation().size() > 1 - || ssdRootAdapter.currentElem.getSubstation().size() != 1) { - throw new ScdException("SCD file must have one or zero Substation and " + - "SCD file must have one Substation. The files are rejected."); - } - TSubstation ssdTSubstation = ssdRootAdapter.currentElem.getSubstation().get(0); - if (scdRootAdapter.getCurrentElem().getSubstation().isEmpty()) { - scdRootAdapter.getCurrentElem().getSubstation().add(ssdTSubstation); - return scdRootAdapter; - } else { - TSubstation scdTSubstation = scdRootAdapter.currentElem.getSubstation().get(0); - if (scdTSubstation.getName().equalsIgnoreCase(ssdTSubstation.getName())) { - SubstationAdapter scdSubstationAdapter = scdRootAdapter.getSubstationAdapter(scdTSubstation.getName()); - for (TVoltageLevel tvl : ssdTSubstation.getVoltageLevel()) { - updateVoltageLevel(scdSubstationAdapter, tvl); - } - } else - throw new ScdException("SCD file must have only one Substation and the Substation name from SSD file is" + - " different from the one in SCD file. The files are rejected."); - } - return scdRootAdapter; - } - - private static 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")); - for (TBay tbay : vl.getBay()) { - updateBay(scdVoltageLevelAdapter, tbay); - } - } else { - scdSubstationAdapter.getCurrentElem().getVoltageLevel().add(vl); - } - } - - private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapter, TBay tBay) { - if (scdVoltageLevelAdapter.getBayAdapter(tBay.getName()).isPresent()) { - scdVoltageLevelAdapter.getCurrentElem().getBay() - .removeIf(t -> t.getName().equalsIgnoreCase(tBay.getName())); - scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); - } else { - scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); - } - } - public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdRootAdapter, Set stds, Map, List> comMap) throws ScdException { @@ -412,7 +345,7 @@ public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdR for (Map.Entry entry : mapIEDNameAndPrivate.entrySet()) { String iedName = entry.getKey(); TPrivate tPrivate = entry.getValue(); - String icdSysVerUuid = getCompasICDHeaderValue(tPrivate).map(TCompasICDHeader::getICDSystemVersionUUID).orElseThrow( + String icdSysVerUuid = PrivateService.getCompasICDHeader(tPrivate).map(TCompasICDHeader::getICDSystemVersionUUID).orElseThrow( () -> new ScdException(ICD_SYSTEM_VERSION_UUID + " is not present in COMPAS-ICDHeader in LNode") ); @@ -422,7 +355,7 @@ public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdR SCL std = mapICDSystemVersionUuidAndSTDFile.get(icdSysVerUuid).getRight().get(0); SclRootAdapter stdRootAdapter = new SclRootAdapter(std); IEDAdapter stdIedAdapter = new IEDAdapter(stdRootAdapter, std.getIED().get(0)); - Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(CommonConstants.COMPAS_ICDHEADER); + Optional optionalTPrivate = stdIedAdapter.getPrivateHeader(COMPAS_ICDHEADER.getPrivateType()); if (optionalTPrivate.isPresent() && comparePrivateCompasICDHeaders(optionalTPrivate.get(), tPrivate)) { copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(optionalTPrivate.get(), tPrivate); } else throw new ScdException("COMPAS-ICDHeader is not the same in Substation and in IED"); @@ -445,11 +378,12 @@ private static void checkSTDCorrespondanceWithLNodeCompasICDHeader(Map new ScdException(CommonConstants.COMPAS_ICDHEADER + "not found in LNode Private ")); - return iedCompasICDHeader.getIEDType().equals(scdCompasICDHeader.getIEDType()) + TCompasICDHeader iedCompasICDHeader = PrivateService.getCompasICDHeader(iedPrivate).orElseThrow( + () -> new ScdException(COMPAS_ICDHEADER + "not found in IED Private ")); + TCompasICDHeader scdCompasICDHeader = PrivateService.getCompasICDHeader(scdPrivate).orElseThrow( + () -> new ScdException(COMPAS_ICDHEADER + "not found in LNode Private ")); + return iedCompasICDHeader.getIEDType().equals(scdCompasICDHeader.getIEDType()) && iedCompasICDHeader.getICDSystemVersionUUID().equals(scdCompasICDHeader.getICDSystemVersionUUID()) && iedCompasICDHeader.getVendorName().equals(scdCompasICDHeader.getVendorName()) && iedCompasICDHeader.getIEDredundancy().equals(scdCompasICDHeader.getIEDredundancy()) @@ -495,21 +429,10 @@ private static boolean comparePrivateCompasICDHeaders(TPrivate iedPrivate, TPriv } private static void copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(TPrivate stdPrivate, TPrivate lNodePrivate) throws ScdException { - JAXBElement lNodeCompasICDHeader = getCompasICDHeader(lNodePrivate).orElseThrow( - () -> new ScdException(CommonConstants.COMPAS_ICDHEADER + "not found in LNode Private ")); + TCompasICDHeader lNodeCompasICDHeader = PrivateService.getCompasICDHeader(lNodePrivate).orElseThrow( + () -> new ScdException(COMPAS_ICDHEADER + " not found in LNode Private ")); stdPrivate.getContent().clear(); - stdPrivate.getContent().add(lNodeCompasICDHeader); - } - - private static Optional> getCompasICDHeader(TPrivate tPrivate) { - return !tPrivate.getType().equals(CommonConstants.COMPAS_ICDHEADER) ? Optional.empty() : - tPrivate.getContent().stream() - .filter(JAXBElement.class::isInstance) - .map(o -> (JAXBElement) o) - .findFirst(); - } - private static Optional getCompasICDHeaderValue(TPrivate tPrivate) { - return getCompasICDHeader(tPrivate).map(JAXBElement::getValue); + stdPrivate.getContent().add(objectFactory.createICDHeader(lNodeCompasICDHeader)); } public static void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final SCL scl) { @@ -530,4 +453,5 @@ public static void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final S .map(LDeviceAdapter::getLNAdapters).flatMap(List::stream) .forEach(LNAdapter::removeAllControlBlocksAndDatasets); } + } 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/scl/SubstationService.java new file mode 100644 index 000000000..3b27c0afe --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SubstationService.java @@ -0,0 +1,89 @@ +// 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.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.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.sstation.BayAdapter; +import org.lfenergy.compas.sct.commons.scl.sstation.FunctionAdapter; +import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; +import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter; + +@Slf4j +public final class SubstationService { + + private SubstationService() { + throw new UnsupportedOperationException("This service class cannot be instantiated"); + } + + public static SclRootAdapter addSubstation(@NonNull SCL scd, @NonNull SCL ssd) throws ScdException { + SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + SclRootAdapter ssdRootAdapter = new SclRootAdapter(ssd); + if (scdRootAdapter.getCurrentElem().getSubstation().size() > 1) { + throw new ScdException(String.format("SCD file must have 0 or 1 Substation, but got %d", + scdRootAdapter.getCurrentElem().getSubstation().size())); + } + if (ssdRootAdapter.getCurrentElem().getSubstation().size() != 1) { + throw new ScdException(String.format("SSD file must have exactly 1 Substation, but got %d", + ssdRootAdapter.getCurrentElem().getSubstation().size())); + } + TSubstation ssdTSubstation = ssdRootAdapter.currentElem.getSubstation().get(0); + if (scdRootAdapter.getCurrentElem().getSubstation().isEmpty()) { + scdRootAdapter.getCurrentElem().getSubstation().add(ssdTSubstation); + return scdRootAdapter; + } else { + TSubstation scdTSubstation = scdRootAdapter.currentElem.getSubstation().get(0); + if (scdTSubstation.getName().equalsIgnoreCase(ssdTSubstation.getName())) { + SubstationAdapter scdSubstationAdapter = scdRootAdapter.getSubstationAdapter(scdTSubstation.getName()); + for (TVoltageLevel tvl : ssdTSubstation.getVoltageLevel()) { + updateVoltageLevel(scdSubstationAdapter, tvl); + } + } else + throw new ScdException("SCD file must have only one Substation and the Substation name from SSD file is" + + " different from the one in SCD file. The files are rejected."); + } + return scdRootAdapter; + } + + private static 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")); + for (TBay tbay : vl.getBay()) { + updateBay(scdVoltageLevelAdapter, tbay); + } + } else { + scdSubstationAdapter.getCurrentElem().getVoltageLevel().add(vl); + } + } + + private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapter, TBay tBay) { + if (scdVoltageLevelAdapter.getBayAdapter(tBay.getName()).isPresent()) { + scdVoltageLevelAdapter.getCurrentElem().getBay() + .removeIf(t -> t.getName().equalsIgnoreCase(tBay.getName())); + scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); + } else { + scdVoltageLevelAdapter.getCurrentElem().getBay().add(tBay); + } + } + + public static void updateLNodeIEDNames(SCL scd) throws ScdException { + if (!scd.isSetSubstation()) { + return; + } + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + + scd.getSubstation().stream().map(tSubstation -> new SubstationAdapter(sclRootAdapter, tSubstation)) + .flatMap(SubstationAdapter::streamVoltageLevelAdapters) + .flatMap(VoltageLevelAdapter::streamBayAdapters) + .flatMap(BayAdapter::streamFunctionAdapters) + .forEach(FunctionAdapter::updateLNodeIedNames); + } +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java index 37d54dd67..e4b5caf42 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/CommunicationAdapter.java @@ -6,7 +6,6 @@ import org.lfenergy.compas.scl2007b4.model.TCommunication; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.scl2007b4.model.TSubNetwork; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; @@ -33,11 +32,6 @@ public boolean amChildElementRef() { return currentElem == parentAdapter.getCurrentElem().getCommunication(); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - public SubNetworkAdapter addSubnetwork(String snName, String snType, String iedName, String apName) throws ScdException { diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java index 280b15fba..e62b5962e 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/ConnectedAPAdapter.java @@ -6,7 +6,6 @@ import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TConnectedAP; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import java.util.Optional; @@ -22,11 +21,6 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getConnectedAP().contains(currentElem); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - public String getIedName() { return currentElem.getIedName(); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/SubNetworkAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/SubNetworkAdapter.java index 1d34883d6..4f06df43a 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/SubNetworkAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/com/SubNetworkAdapter.java @@ -6,7 +6,6 @@ import lombok.NonNull; import org.lfenergy.compas.scl2007b4.model.TConnectedAP; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.scl2007b4.model.TSubNetwork; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; @@ -26,11 +25,6 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSubNetwork().contains(currentElem); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - /** * Create a Connected Access Point for this subnetwork. * Note : this method doesn't check the validity on neither the IED name nor the access point name. diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/AbstractDataAttributeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/AbstractDataAttributeAdapter.java index 016217710..e0d745d32 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/AbstractDataAttributeAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/AbstractDataAttributeAdapter.java @@ -6,10 +6,10 @@ import lombok.Getter; import org.lfenergy.compas.scl2007b4.model.*; -import org.lfenergy.compas.sct.commons.Utils; import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.Objects; import java.util.Optional; diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DAAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DAAdapter.java index 47ec0c7ee..55fdbb348 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DAAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DAAdapter.java @@ -6,7 +6,6 @@ import lombok.Getter; import org.lfenergy.compas.scl2007b4.model.TDA; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.exception.ScdException; @@ -29,8 +28,4 @@ public void check(DaTypeName daTypeName) throws ScdException { daTypeName.setFc(currentElem.getFc()); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapter.java index 9e2c796af..cfe8ce5e2 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DATypeAdapter.java @@ -7,7 +7,10 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; -import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.scl2007b4.model.TBDA; +import org.lfenergy.compas.scl2007b4.model.TDAType; +import org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum; +import org.lfenergy.compas.scl2007b4.model.TProtNs; import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; import org.lfenergy.compas.sct.commons.exception.ScdException; @@ -243,11 +246,6 @@ public DataTypeTemplateAdapter getDataTypeTemplateAdapter() { return parentAdapter; } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - public Optional getBdaAdapterByName(String name) { Optional opBda = getBDAByName(name); if(opBda.isPresent()){ @@ -270,9 +268,5 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getBDA().contains(currentElem); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOAdapter.java index 13da0257a..b07157329 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOAdapter.java @@ -5,7 +5,6 @@ package org.lfenergy.compas.sct.commons.scl.dtt; import org.lfenergy.compas.scl2007b4.model.TDO; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import java.util.Optional; @@ -29,11 +28,6 @@ public Optional getDoTypeAdapter() { return getDataTypeTemplateAdapter().getDOTypeAdapterById(currentElem.getType()); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - public String getType() { return currentElem.getType(); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapter.java index 84c3a7166..e242b66a9 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapter.java @@ -125,11 +125,6 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getDOType().contains(currentElem); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - public boolean containsDAWithDAName(String da){ return currentElem.getSDOOrDA() .stream() diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapter.java index b707f104f..160b00ff2 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapter.java @@ -31,11 +31,6 @@ protected boolean amChildElementRef() { return currentElem == parentAdapter.getCurrentElem().getDataTypeTemplates(); } - @Override - protected void addPrivate(TPrivate tPrivate) { - throw new IllegalArgumentException("Private is not Allowed here"); - } - public Optional getLNodeTypeAdapterById(String id) { for(TLNodeType tlNodeType : currentElem.getLNodeType()){ if(tlNodeType.getId().equals(id)) { diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/EnumTypeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/EnumTypeAdapter.java index 8aa1c52eb..d7464cdf1 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/EnumTypeAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/EnumTypeAdapter.java @@ -7,7 +7,6 @@ import org.lfenergy.compas.scl2007b4.model.TEnumType; import org.lfenergy.compas.scl2007b4.model.TEnumVal; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import java.util.List; import java.util.Objects; @@ -54,8 +53,4 @@ public DataTypeTemplateAdapter getDataTypeTemplateAdapter() { return parentAdapter; } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapter.java index 48c425c0d..9a55dcd0e 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapter.java @@ -10,7 +10,6 @@ import org.lfenergy.compas.scl2007b4.model.TDO; import org.lfenergy.compas.scl2007b4.model.TLNodeType; import org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.dto.DoTypeName; import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; @@ -69,11 +68,6 @@ public boolean hasSameContentAs(TLNodeType tlNodeType) { return true; } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - public boolean containsDOWithDOTypeId(String doTypeId) { return currentElem.getDO().stream() .anyMatch(tdo -> tdo.getType().equals(doTypeId)); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/header/HeaderAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/header/HeaderAdapter.java index 1f8500b55..aa5e5ac90 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/header/HeaderAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/header/HeaderAdapter.java @@ -7,7 +7,6 @@ import org.lfenergy.compas.scl2007b4.model.THeader; import org.lfenergy.compas.scl2007b4.model.THitem; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; @@ -46,11 +45,6 @@ public HeaderAdapter addHistoryItem(String who, String what, String why){ return this; } - @Override - protected void addPrivate(TPrivate tPrivate) { - throw new IllegalArgumentException("Private is not Allowed here"); - } - public String getHeaderId() { return currentElem.getId(); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/DOIAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/DOIAdapter.java index f687df296..5e2fd381d 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/DOIAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/DOIAdapter.java @@ -4,7 +4,10 @@ package org.lfenergy.compas.sct.commons.scl.ied; -import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.scl2007b4.model.TAnyLN; +import org.lfenergy.compas.scl2007b4.model.TDAI; +import org.lfenergy.compas.scl2007b4.model.TDOI; +import org.lfenergy.compas.scl2007b4.model.TSDI; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; @@ -36,11 +39,6 @@ public RootSDIAdapter getStructuredDataAdapterByName(String sName) throws ScdExc ); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - @Override public DAIAdapter getDataAdapterByName(String daName) throws ScdException { return currentElem.getSDIOrDAI() @@ -85,9 +83,5 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSDIOrDAI().contains(currentElem); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } } } 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 1d79e330a..ba9651a8d 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 @@ -128,11 +128,6 @@ public boolean findAccessPointByName(String apName) { .anyMatch(tAccessPoint -> tAccessPoint.getName().equals(apName)); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - public List getExtRefBinders(@NonNull ExtRefSignalInfo signalInfo) throws ScdException { if(!signalInfo.isValid()){ throw new ScdException("Invalid ExtRef signal (pDO,pDA or intAddr))"); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapter.java index fdfbf6f89..780e983a0 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapter.java @@ -9,7 +9,6 @@ import org.apache.commons.lang3.StringUtils; import org.lfenergy.compas.scl2007b4.model.TLDevice; import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; @@ -145,8 +144,4 @@ public Set getDAI(ResumedDataTemplate rDtt, boolean updatab } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } } 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 4d86941a4..de6bebe65 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 @@ -7,7 +7,6 @@ import org.lfenergy.compas.scl2007b4.model.LN0; import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; -import org.lfenergy.compas.scl2007b4.model.TPrivate; public class LN0Adapter extends AbstractLNAdapter { @@ -40,11 +39,6 @@ public String getPrefix() { return ""; } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - @Override protected boolean matchesDataAttributes(String dataAttribute){ return super.matchesDataAttributes(dataAttribute) || diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LNAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LNAdapter.java index 9092eef7a..f281540a5 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LNAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LNAdapter.java @@ -3,8 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 package org.lfenergy.compas.sct.commons.scl.ied; + import org.lfenergy.compas.scl2007b4.model.TLN; -import org.lfenergy.compas.scl2007b4.model.TPrivate; public class LNAdapter extends AbstractLNAdapter{ @@ -27,11 +27,6 @@ public String getLNClass() { return null; } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - @Override public String getLNInst() { return currentElem.getInst(); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/RootSDIAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/RootSDIAdapter.java index 61591dd34..39f04e794 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/RootSDIAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/RootSDIAdapter.java @@ -5,7 +5,6 @@ package org.lfenergy.compas.sct.commons.scl.ied; import org.lfenergy.compas.scl2007b4.model.TDAI; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.scl2007b4.model.TSDI; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; @@ -66,11 +65,6 @@ public IDataParentAdapter addSDOI(String sdoName) { return new SDIAdapter(this,tsdi); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - public static class DAIAdapter extends AbstractDAIAdapter { public DAIAdapter(RootSDIAdapter rootSDIAdapter, TDAI tdai) { @@ -82,9 +76,5 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSDIOrDAI().contains(currentElem); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/SDIAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/SDIAdapter.java index 0dc215132..245cb1dba 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/SDIAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/SDIAdapter.java @@ -5,7 +5,6 @@ package org.lfenergy.compas.sct.commons.scl.ied; import org.lfenergy.compas.scl2007b4.model.TDAI; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.scl2007b4.model.TSDI; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; @@ -76,11 +75,6 @@ public SDIAdapter addSDOI(String sdoName) { return new SDIAdapter(this,tsdi); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } - public static class DAIAdapter extends AbstractDAIAdapter { protected DAIAdapter(SDIAdapter parentAdapter, TDAI currentElem) { @@ -92,9 +86,5 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSDIOrDAI().contains(currentElem); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); - } } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/BayAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/BayAdapter.java index 21737c0ae..7c178bc49 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/BayAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/BayAdapter.java @@ -4,9 +4,11 @@ package org.lfenergy.compas.sct.commons.scl.sstation; import org.lfenergy.compas.scl2007b4.model.TBay; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; + +import java.util.stream.Stream; public class BayAdapter extends SclElementAdapter { @@ -32,7 +34,14 @@ protected boolean amChildElementRef() { } @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); + protected String elementXPath() { + return String.format("Bay[%s]", Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + + public Stream streamFunctionAdapters(){ + if (!currentElem.isSetFunction()){ + return Stream.empty(); + } + return currentElem.getFunction().stream().map(tFunction -> new FunctionAdapter(this, tFunction)); } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/FunctionAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/FunctionAdapter.java new file mode 100644 index 000000000..c2062ea26 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/FunctionAdapter.java @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2021 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.sct.commons.scl.sstation; + +import org.apache.commons.lang3.StringUtils; +import org.lfenergy.compas.scl2007b4.model.TCompasICDHeader; +import org.lfenergy.compas.scl2007b4.model.TFunction; +import org.lfenergy.compas.scl2007b4.model.TLNode; +import org.lfenergy.compas.scl2007b4.model.TPrivate; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.PrivateService; +import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; + +import java.util.List; +import java.util.ListIterator; +import java.util.stream.Collectors; + +import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_ICDHEADER; + +public class FunctionAdapter extends SclElementAdapter { + + public FunctionAdapter(BayAdapter parentAdapter, TFunction currentElem) { + super(parentAdapter, currentElem); + } + + @Override + protected boolean amChildElementRef() { + return parentAdapter.getCurrentElem().getFunction().contains(currentElem); + } + + @Override + protected String elementXPath() { + return String.format("Function[%s]", Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + + public void updateLNodeIedNames() throws ScdException { + if (!currentElem.isSetLNode()) { + return; + } + // use ListIterator to add & remove items in place + ListIterator lNodeIterator = currentElem.getLNode().listIterator(); + while (lNodeIterator.hasNext()) { + TLNode lNode = lNodeIterator.next(); + List icdHeaders = PrivateService.getCompasPrivates(lNode, TCompasICDHeader.class); + if (icdHeaders.isEmpty()){ + throw new ScdException(getXPath() + " doesn't contain any Private/compas:ICDHeader"); + } + if (icdHeaders.size() == 1) { + setLNodeIedName(lNode, icdHeaders.get(0).getIEDName()); + } else { + lNodeIterator.remove(); + PrivateService.removePrivates(lNode, COMPAS_ICDHEADER); + List newLNodes = distributeIcdHeaders(lNode, icdHeaders); + newLNodes.forEach(lNodeIterator::add); + } + } + } + + private List distributeIcdHeaders(TLNode lNode, List compasICDHeaders) { + LNodeAdapter lNodeAdapter = new LNodeAdapter(null, lNode); + return compasICDHeaders.stream().map(compasICDHeader -> { + TPrivate icdHeaderPrivate = PrivateService.createPrivate(compasICDHeader); + TLNode newLNode = lNodeAdapter.deepCopy(); + newLNode.getPrivate().add(icdHeaderPrivate); + setLNodeIedName(newLNode, compasICDHeader.getIEDName()); + return newLNode; + }).collect(Collectors.toList()); + } + + private void setLNodeIedName(TLNode lNode, String privateIedName) { + if (StringUtils.isBlank(privateIedName)){ + LNodeAdapter lNodeAdapter = new LNodeAdapter(null, lNode); + throw new ScdException(getXPath() + lNodeAdapter.getXPath() + "/Private/compas:ICDHeader/@IEDName is missing or is blank"); + } + lNode.setIedName(privateIedName); + } +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapter.java new file mode 100644 index 000000000..51fec68b9 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapter.java @@ -0,0 +1,64 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.scl.sstation; + +import org.lfenergy.compas.scl2007b4.model.TFunction; +import org.lfenergy.compas.scl2007b4.model.TLNode; +import org.lfenergy.compas.scl2007b4.model.TText; +import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; + +public class LNodeAdapter extends SclElementAdapter { + + public LNodeAdapter(FunctionAdapter parentAdapter, TLNode currentElem) { + super(parentAdapter, currentElem); + } + + @Override + protected boolean amChildElementRef() { + TFunction parentElem = parentAdapter.getCurrentElem(); + return parentElem.isSetLNode() && parentElem.getLNode().contains(this.currentElem); + } + + public TLNode deepCopy() { + TLNode newLNode = new TLNode(); + newLNode.setDesc(currentElem.getDesc()); + newLNode.setIedName(currentElem.getIedName()); + newLNode.setLdInst(currentElem.getLdInst()); + newLNode.setLnInst(currentElem.getLnInst()); + newLNode.setLnType(currentElem.getLnType()); + newLNode.setPrefix(currentElem.getPrefix()); + if (currentElem.isSetText()) { + TText newText = new TText(); + newText.setSource(currentElem.getText().getSource()); + newText.getContent().addAll(currentElem.getText().getContent()); + newText.getOtherAttributes().putAll(currentElem.getText().getOtherAttributes()); + newLNode.setText(newText); + } + if (currentElem.isSetPrivate()) { + newLNode.getPrivate().addAll(currentElem.getPrivate()); + } + if (currentElem.isSetLnClass()) { + newLNode.getLnClass().addAll(currentElem.getLnClass()); + } + if (currentElem.isSetAny()) { + newLNode.getAny().addAll(currentElem.getAny()); + } + newLNode.getOtherAttributes().putAll(currentElem.getOtherAttributes()); + return newLNode; + } + + @Override + protected String elementXPath() { + return String.format("LNode[%s and %s and %s and %s and %s]", + Utils.xpathAttributeFilter("iedName", currentElem.isSetIedName() ? currentElem.getIedName() : null), + Utils.xpathAttributeFilter("ldInst", currentElem.isSetLdInst() ? currentElem.getLdInst() : null), + Utils.xpathAttributeFilter("Prefix", currentElem.isSetPrefix() ? currentElem.getPrefix() : null), + Utils.xpathAttributeFilter("lnClass", currentElem.isSetLnClass() ? currentElem.getLnClass() : null), + Utils.xpathAttributeFilter("lnInst", currentElem.isSetLnInst() ? currentElem.getLnInst() : null) + ); + } + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/SubstationAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/SubstationAdapter.java index 605b4df9f..6b1e34200 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/SubstationAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/SubstationAdapter.java @@ -4,13 +4,14 @@ package org.lfenergy.compas.sct.commons.scl.sstation; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.scl2007b4.model.TSubstation; 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.util.Utils; import java.util.Optional; +import java.util.stream.Stream; public class SubstationAdapter extends SclElementAdapter { @@ -37,6 +38,11 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSubstation().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("Substation[%s]", Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + public Optional getVoltageLevelAdapter(String vLevelName) { return currentElem.getVoltageLevel() .stream() @@ -45,8 +51,11 @@ public Optional getVoltageLevelAdapter(String vLevelName) { .findFirst(); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); + public Stream streamVoltageLevelAdapters() { + if (!currentElem.isSetVoltageLevel()){ + return Stream.empty(); + } + return currentElem.getVoltageLevel().stream().map(tVoltageLevel -> new VoltageLevelAdapter(this, tVoltageLevel)); } + } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/VoltageLevelAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/VoltageLevelAdapter.java index 96b035566..de7408704 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/VoltageLevelAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/sstation/VoltageLevelAdapter.java @@ -3,12 +3,13 @@ // SPDX-License-Identifier: Apache-2.0 package org.lfenergy.compas.sct.commons.scl.sstation; -import org.lfenergy.compas.scl2007b4.model.TPrivate; import org.lfenergy.compas.scl2007b4.model.TVoltageLevel; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.Optional; +import java.util.stream.Stream; public class VoltageLevelAdapter extends SclElementAdapter { @@ -28,12 +29,16 @@ public VoltageLevelAdapter(SubstationAdapter parentAdapter, String vLevelName) t setCurrentElem(tVoltageLevel); } - @Override protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getVoltageLevel().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("VoltageLevel[%s]", Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + public Optional getBayAdapter(String bayName) { return currentElem.getBay() .stream() @@ -42,8 +47,11 @@ public Optional getBayAdapter(String bayName) { .findFirst(); } - @Override - protected void addPrivate(TPrivate tPrivate) { - currentElem.getPrivate().add(tPrivate); + public Stream streamBayAdapters() { + if (!currentElem.isSetBay()){ + return Stream.empty(); + } + return currentElem.getBay().stream().map(tBay -> new BayAdapter(this, tBay)); } + } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/CommonConstants.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/CommonConstants.java new file mode 100644 index 000000000..752d71b0f --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/CommonConstants.java @@ -0,0 +1,18 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.util; + +public final class CommonConstants { + + public static final String ICD_SYSTEM_VERSION_UUID = "ICDSystemVersionUUID"; + public static final String IED_NAME = "IEDName"; + public static final String HEADER_ID = "headerId"; + public static final String HEADER_VERSION = "headerVersion"; + public static final String HEADER_REVISION = "headerRevision"; + + private CommonConstants() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/PrivateEnum.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/PrivateEnum.java new file mode 100644 index 000000000..b9a1f8fa5 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/PrivateEnum.java @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.util; + +import lombok.Getter; +import org.lfenergy.compas.scl2007b4.model.*; + +import javax.validation.constraints.NotNull; +import java.util.Arrays; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.function.Function; +import java.util.stream.Collectors; + +public enum PrivateEnum { + + COMPAS_BAY("COMPAS-Bay", TCompasBay.class), + COMPAS_CRITERIA("COMPAS-Criteria", TCompasCriteria.class), + COMPAS_FLOW("COMPAS-Flow", TCompasFlow.class), + COMPAS_FUNCTION("COMPAS-Function", TCompasFunction.class), + COMPAS_ICDHEADER("COMPAS-ICDHeader", TCompasICDHeader.class), + COMPAS_LDEVICE("COMPAS-LDevice", TCompasLDevice.class), + COMPAS_SCL_FILE_TYPE("COMPAS-SclFileType", TCompasSclFileType.class), + COMPAS_SYSTEM_VERSION("COMPAS-SystemVersion", TCompasSystemVersion.class); + + private static final Map, PrivateEnum> classToEnum = Arrays.stream(PrivateEnum.values()).collect(Collectors.toMap( + compasPrivateEnum -> compasPrivateEnum.compasClass, + Function.identity())); + + @Getter + private final String privateType; + @Getter + private final Class compasClass; + + PrivateEnum(String privateType, Class compasClass) { + this.privateType = privateType; + this.compasClass = compasClass; + } + + @NotNull + public static PrivateEnum fromClass(Class compasClass) { + PrivateEnum result = classToEnum.get(compasClass); + if (result == null) { + throw new NoSuchElementException(String.format("Class %s is not mapped to a compas type. See %s", compasClass.getName(), + PrivateEnum.class.getName())); + } + return result; + } + + @Override + public String toString() { + return privateType; + } + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/Utils.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/Utils.java similarity index 67% rename from sct-commons/src/main/java/org/lfenergy/compas/sct/commons/Utils.java rename to sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/Utils.java index 8ca0711d2..cb84ae828 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/Utils.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/Utils.java @@ -1,23 +1,25 @@ -// SPDX-FileCopyrightText: 2021 RTE FRANCE +// SPDX-FileCopyrightText: 2022 RTE FRANCE // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons; +package org.lfenergy.compas.sct.commons.util; import lombok.extern.slf4j.Slf4j; +import java.util.Collection; import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Collectors; @Slf4j -public class Utils { +public final class Utils { public static final String LEAVING_PREFIX = "<<< Leaving: ::"; public static final String ENTERING_PREFIX = ">>> Entering: ::"; private Utils() { - throw new IllegalStateException("Utils class"); + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); } public static String entering() { @@ -70,4 +72,19 @@ public static boolean equalsOrNotSet(T o1, T o2, Predicate isSet, Func return Objects.equals(getValue.apply(o1), getValue.apply(o2)); } + public static String xpathAttributeFilter(String name, String value) { + if (value == null){ + return String.format("not(@%s)", name); + } else { + return String.format("@%s=\"%s\"", name, value); + } + } + + public static String xpathAttributeFilter(String name, Collection value) { + if (value == null || value.isEmpty() || value.stream().allMatch(Objects::isNull)){ + return String.format("not(@%s)", name); + } else { + return xpathAttributeFilter(name, value.stream().filter(Objects::nonNull).collect(Collectors.joining(" "))); + } + } } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/CommonConstantsTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/CommonConstantsTest.java deleted file mode 100644 index c2708084e..000000000 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/CommonConstantsTest.java +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-FileCopyrightText: 2021 RTE FRANCE -// -// SPDX-License-Identifier: Apache-2.0 - -package org.lfenergy.compas.sct.commons; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - - -class CommonConstantsTest { - @Test - void testShouldReturnNOKWhenConstructClassCauseForbidden() { - assertThrows(UnsupportedOperationException.class, CommonConstants::new); - } - -} \ No newline at end of file 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/scl/PrivateServiceTest.java new file mode 100644 index 000000000..e3213f04d --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/PrivateServiceTest.java @@ -0,0 +1,253 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.scl; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +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.exception.ScdException; +import org.lfenergy.compas.sct.commons.util.PrivateEnum; + +import javax.xml.bind.JAXBElement; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class PrivateServiceTest { + + private TPrivate privateSCD; + private TPrivate privateICD; + private ObjectFactory objectFactory; + + @BeforeEach + void setUp() { + objectFactory = new ObjectFactory(); + privateSCD = objectFactory.createTPrivate(); + privateSCD.setType(PrivateEnum.COMPAS_SCL_FILE_TYPE.getPrivateType()); + privateSCD.getContent().add(objectFactory.createSclFileType(TCompasSclFileType.SCD)); + privateICD = objectFactory.createTPrivate(); + privateICD.setType(PrivateEnum.COMPAS_SCL_FILE_TYPE.getPrivateType()); + privateICD.getContent().add(objectFactory.createSclFileType(TCompasSclFileType.ICD)); + } + + @Test + void class_should_not_be_instantiable() { + // Given + Constructor[] constructors = PrivateService.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); + } + + @Test + void getCompasPrivates_should_return_privates_value() { + // Given : setUp + // When + List result = PrivateService.getCompasPrivates(List.of(privateSCD, privateICD), + TCompasSclFileType.class); + //Then + assertThat(result) + .hasSize(2) + .containsExactly(TCompasSclFileType.SCD, TCompasSclFileType.ICD); + } + + @Test + void getCompasPrivates_when_no_privates_match_class_should_return_empty_list() { + // Given : setUp + // When + List result = PrivateService.getCompasPrivates(List.of(privateSCD), TCompasICDHeader.class); + //Then + assertThat(result).isEmpty(); + } + + @Test + void getCompasPrivates_when_class_is_not_compas_class_should_throw_exception() { + // Given : setUp + List privates = List.of(privateSCD); + // When & Then + assertThatThrownBy(() -> PrivateService.getCompasPrivates(privates, Object.class)).isInstanceOf( + NoSuchElementException.class); + } + + @Test + void getCompasPrivates_when_content_not_match_private_type_should_throw_exception() { + // Given : setUp + privateSCD.setType(PrivateEnum.COMPAS_BAY.getPrivateType()); + Class compasClass = PrivateEnum.COMPAS_BAY.getCompasClass(); + List privates = List.of(privateSCD); + // When & Then + assertThatThrownBy(() -> PrivateService.getCompasPrivates(privates, compasClass)).isInstanceOf( + ScdException.class); + } + + @Test + void getCompasPrivates_on_base_element_should_return_privates_value() { + // Given : setUp + TBaseElement baseElement = new SCL(); + baseElement.getPrivate().add(privateSCD); + baseElement.getPrivate().add(privateICD); + // When + List result = PrivateService.getCompasPrivates(baseElement, TCompasSclFileType.class); + // Then + assertThat(result) + .hasSize(2) + .containsExactly(TCompasSclFileType.SCD, TCompasSclFileType.ICD); + } + + @Test + void getCompasPrivates_on_base_element_should_not_set_private() { + // Given + TBaseElement baseElement = new SCL(); + // When + PrivateService.getCompasPrivates(baseElement, TCompasSclFileType.class); + // Then + assertThat(baseElement.isSetPrivate()).isFalse(); + } + + @Test + void getCompasPrivate_should_return_private_value() { + // Given : setUp + // When + Optional result = PrivateService.getCompasPrivate(privateSCD, + TCompasSclFileType.class); + //Then + assertThat(result).isPresent() + .hasValue(TCompasSclFileType.SCD); + } + + @Test + void getCompasPrivate_should_return_empty() { + // Given : setUp + // When + Optional result = PrivateService.getCompasPrivate(privateSCD, + TCompasBay.class); + //Then + assertThat(result).isNotPresent(); + } + + @Test + void getCompasPrivate_should_throw_exception() { + // Given : setUp + privateSCD.getContent().add(objectFactory.createSclFileType(TCompasSclFileType.ICD)); + Class compasClass = PrivateEnum.COMPAS_SCL_FILE_TYPE.getCompasClass(); + // When & Then + assertThatThrownBy(() -> PrivateService.getCompasPrivate(privateSCD, compasClass)).isInstanceOf( + ScdException.class); + } + + @Test + void getCompasICDHeader_should_return_private_value() { + // Given + privateSCD = objectFactory.createTPrivate(); + privateSCD.setType(PrivateEnum.COMPAS_ICDHEADER.getPrivateType()); + TCompasICDHeader tCompasICDHeader = objectFactory.createTCompasICDHeader(); + privateSCD.getContent().add(objectFactory.createICDHeader(tCompasICDHeader)); + // When + Optional optionalResult = PrivateService.getCompasICDHeader(privateSCD); + //Then + assertThat(optionalResult).isPresent().get().matches(result -> result == tCompasICDHeader); + } + + @ParameterizedTest + @MethodSource("createPrivateTestSources") + void createPrivate_should_return_private_new_private(Object compasElement) throws InvocationTargetException, IllegalAccessException { + // Given + PrivateEnum privateEnum = PrivateEnum.fromClass(compasElement.getClass()); + assertThat(privateEnum).isNotNull(); + Optional optionalCreatePrivateMethod = ReflectionSupport.findMethod(PrivateService.class, "createPrivate", compasElement.getClass()); + assertThat(optionalCreatePrivateMethod).isPresent(); + Method createPrivateMethod = optionalCreatePrivateMethod.get(); + // When + Object result = createPrivateMethod.invoke(null, compasElement); + //Then + assertThat(result).isInstanceOf(TPrivate.class); + TPrivate resultPrivate = (TPrivate) result; + assertThat(resultPrivate).isNotNull() + .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); + } + + public static Stream createPrivateTestSources() { + return Stream.of(new TCompasBay(), + new TCompasCriteria(), + new TCompasFlow(), + new TCompasFunction(), + new TCompasICDHeader(), + new TCompasLDevice(), + TCompasSclFileType.SCD, + new TCompasSystemVersion()); + } + + @Test + void removePrivates_should_remove_privates() { + // Given : setUp + TBaseElement baseElement = new SCL(); + baseElement.getPrivate().add(privateSCD); + // When + PrivateService.removePrivates(baseElement, PrivateEnum.COMPAS_SCL_FILE_TYPE); + // Then + assertThat(baseElement.isSetPrivate()).isFalse(); + } + + @Test + void removePrivates_should_do_nothing_when_no_private_match_type() { + // Given : setUp + TBaseElement baseElement = new SCL(); + baseElement.getPrivate().add(privateSCD); + // When + PrivateService.removePrivates(baseElement, PrivateEnum.COMPAS_ICDHEADER); + // Then + assertThat(baseElement.getPrivate()).hasSize(1); + } + + @Test + void removePrivates_should_remove_privates_of_given_type() { + // Given : setUp + TBaseElement baseElement = new SCL(); + baseElement.getPrivate().add(privateSCD); + TCompasICDHeader tCompasICDHeader = objectFactory.createTCompasICDHeader(); + baseElement.getPrivate().add(PrivateService.createPrivate(tCompasICDHeader)); + // When + PrivateService.removePrivates(baseElement, PrivateEnum.COMPAS_ICDHEADER); + // Then + assertThat(baseElement.getPrivate()).hasSize(1); + TPrivate tPrivate = baseElement.getPrivate().get(0); + assertThat(tPrivate.getType()).isEqualTo(privateSCD.getType()); + assertThat(tPrivate.getContent()).hasSize(1).first().isInstanceOf(JAXBElement.class); + JAXBElement jaxbElement = (JAXBElement) tPrivate.getContent().get(0); + assertThat(jaxbElement.isNil()).isFalse(); + assertThat(jaxbElement.getValue()).isEqualTo(TCompasSclFileType.SCD); + } + + @Test + void removePrivates_should_not_set_private() { + // Given : setUp + TBaseElement baseElement = new SCL(); + baseElement.unsetPrivate(); + // When + PrivateService.removePrivates(baseElement, PrivateEnum.COMPAS_ICDHEADER); + // Then + assertThat(baseElement.isSetPrivate()).isFalse(); + } + +} 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/scl/SclServiceTest.java index ce5dc93e9..ddbdb513a 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/scl/SclServiceTest.java @@ -6,10 +6,7 @@ import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Test; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; import org.lfenergy.compas.scl2007b4.model.*; -import org.lfenergy.compas.sct.commons.CommonConstants; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.ied.*; @@ -23,6 +20,7 @@ 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.SclTestMarshaller.assertIsMarshallable; +import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_SCL_FILE_TYPE; class SclServiceTest { @@ -528,7 +526,7 @@ void testInitScl_Create_Private_SCL_FILETYPE() { () -> SclService.initScl(Optional.of(hid), "hVersion", "hRevision") ); assertThat(rootAdapter.getCurrentElem().getPrivate()).isNotEmpty(); - assertThat(rootAdapter.getCurrentElem().getPrivate().get(0).getType()).isEqualTo(CommonConstants.COMPAS_SCL_FILE_TYPE); + assertThat(rootAdapter.getCurrentElem().getPrivate().get(0).getType()).isEqualTo(COMPAS_SCL_FILE_TYPE.getPrivateType()); assertIsMarshallable(rootAdapter.getCurrentElem()); } @@ -549,7 +547,6 @@ void testUpdateDAI() throws Exception { ResumedDataTemplate rDtt = new ResumedDataTemplate(); rDtt.setLnType("unknownID"); SCL scd = SclTestMarshaller.getSCLFromFile("/ied-test-schema-conf/ied_unit_test.xml"); - SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); assertThrows(ScdException.class, () -> SclService.updateDAI( scd, "IED", "LD", rDtt @@ -577,56 +574,6 @@ void testGetEnumTypeElements() throws Exception { assertFalse(enumList.isEmpty()); } - @ParameterizedTest - @ValueSource(strings = {"/scd-substation-import-ssd/ssd_with_2_substations.xml", "/scd-substation-import-ssd/ssd_without_substations.xml"}) - void testAddSubstation_Check_SSD_Validity(String ssdFileName) throws Exception { - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-root-test-schema-conf/add_ied_test.xml"); - SCL ssd = SclTestMarshaller.getSCLFromFile(ssdFileName); - - assertThrows(ScdException.class, - () -> SclService.addSubstation(scd, ssd)); - assertIsMarshallable(scd); - } - - @Test - void testAddSubstation_SCD_Without_Substation() throws Exception { - SCL scd = SclTestMarshaller.getSCLFromFile("/scl-root-test-schema-conf/add_ied_test.xml"); - SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); - SclRootAdapter ssdRootAdapter = new SclRootAdapter(ssd); - SclRootAdapter expectedScdAdapter = SclService.addSubstation(scd, ssd); - - assertNotEquals(scdRootAdapter, expectedScdAdapter); - assertEquals(expectedScdAdapter.getCurrentElem().getSubstation(), ssdRootAdapter.getCurrentElem().getSubstation()); - assertIsMarshallable(scd); - } - - @Test - void testAddSubstation_SCD_With_Different_Substation_Name() throws 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"); - - assertThrows(ScdException.class, - () -> SclService.addSubstation(scd, ssd)); - assertIsMarshallable(scd); - } - - @Test - void testAddSubstation_SCD_With_Substation() throws Exception { - SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/scd_with_substation.xml"); - SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); - SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); - SclRootAdapter ssdRootAdapter = new SclRootAdapter(ssd); - SclRootAdapter expectedScdAdapter = SclService.addSubstation(scd, ssd); - TSubstation expectedTSubstation = expectedScdAdapter.getCurrentElem().getSubstation().get(0); - TSubstation tSubstation = ssdRootAdapter.getCurrentElem().getSubstation().get(0); - - assertNotEquals(scdRootAdapter, expectedScdAdapter); - assertEquals(expectedTSubstation.getName(), tSubstation.getName()); - assertEquals(expectedTSubstation.getVoltageLevel().size(), tSubstation.getVoltageLevel().size()); - assertIsMarshallable(scd); - } - @Test void testImportSTDElementsInSCD() throws Exception { SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd.xml"); 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/scl/SubstationServiceTest.java new file mode 100644 index 000000000..4f2a23a9e --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SubstationServiceTest.java @@ -0,0 +1,195 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.scl; + +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.scl2007b4.model.TCompasICDHeader; +import org.lfenergy.compas.scl2007b4.model.TLNode; +import org.lfenergy.compas.scl2007b4.model.TSubstation; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; + +import java.util.List; + +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.SclTestMarshaller.assertIsMarshallable; + +class SubstationServiceTest { + + public static final String XPATH_FUNCTION_BAY_1_TDCL = "/SCL/Substation[@name=\"SITE\"]/VoltageLevel[@name=\"voltageLevelName\"]/Bay[@name=\"bay1\"]/Function[@name=\"bay1TDCL\"]"; + + public static final String XPATH_LNODE_RADR = XPATH_FUNCTION_BAY_1_TDCL + "/LNode[@iedName=\"None\" and not(@ldInst) and not(@Prefix) and @lnClass=\"RADR\" and not(@lnInst)]"; + + @Test + void addSubstation_when_SCD_has_no_substation_should_succeed() throws Exception { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-root-test-schema-conf/add_ied_test.xml"); + SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); + SclRootAdapter ssdRootAdapter = new SclRootAdapter(ssd); + // When + SclRootAdapter resultScdAdapter = SubstationService.addSubstation(scd, ssd); + // Then + assertNotEquals(scdRootAdapter, resultScdAdapter); + assertEquals(resultScdAdapter.getCurrentElem().getSubstation(), ssdRootAdapter.getCurrentElem().getSubstation()); + assertIsMarshallable(scd); + } + + @Test + void addSubstation_when_SCD_has_a_substation_should_succeed() throws Exception { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/scd_with_substation.xml"); + SclRootAdapter scdRootAdapter = new SclRootAdapter(scd); + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); + SclRootAdapter ssdRootAdapter = new SclRootAdapter(ssd); + TSubstation ssdSubstation = ssdRootAdapter.getCurrentElem().getSubstation().get(0); + // When + SclRootAdapter resultScdAdapter = SubstationService.addSubstation(scd, ssd); + // Then + TSubstation resultSubstation = resultScdAdapter.getCurrentElem().getSubstation().get(0); + assertNotEquals(scdRootAdapter, resultScdAdapter); + assertEquals(ssdSubstation.getName(), resultSubstation.getName()); + assertEquals(ssdSubstation.getVoltageLevel().size(), resultSubstation.getVoltageLevel().size()); + assertIsMarshallable(scd); + } + + @Test + void addSubstation_when_SSD_with_multiple_Substations_should_throw_exception() throws Exception { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-root-test-schema-conf/add_ied_test.xml"); + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_with_2_substations.xml"); + + // When & Then + assertThrows(ScdException.class, () -> SubstationService.addSubstation(scd, ssd)); + } + + @Test + void addSubstation_when_SSD_with_no_substation_should_throw_exception() throws Exception { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-root-test-schema-conf/add_ied_test.xml"); + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml"); + + // When & Then + assertThrows(ScdException.class, () -> SubstationService.addSubstation(scd, ssd)); + } + + @Test + void addSubstation_when_substations_names_differ_should_throw_exception() throws Exception { + // Given + 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)); + } + + @Test + void updateLNodeIEDNames_when_LNode_has_single_private_should_set_IedName() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/scd-with-substation-lnode.xml"); + // When + SubstationService.updateLNodeIEDNames(scl); + // Then + assertThat(scl.getSubstation()).hasSize(1); + assertThat(scl.getSubstation().get(0).getVoltageLevel()).hasSize(1); + assertThat(scl.getSubstation().get(0).getVoltageLevel().get(0).getBay()).hasSize(1); + assertThat(scl.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0).getFunction()).hasSize(1); + List lNodes = scl.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0).getFunction().get(0).getLNode(); + assertThat(lNodes).extracting(TLNode::getIedName).containsOnlyOnce("iedName1"); + assertIsMarshallable(scl); + } + + @Test + void updateLNodeIEDNames_when_LNode_has_multiples_private_should_set_IedName() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/scd-with-substation-lnode.xml"); + // When + SubstationService.updateLNodeIEDNames(scl); + // Then + assertThat(scl.getSubstation()).hasSize(1); + assertThat(scl.getSubstation().get(0).getVoltageLevel()).hasSize(1); + assertThat(scl.getSubstation().get(0).getVoltageLevel().get(0).getBay()).hasSize(1); + assertThat(scl.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0).getFunction()).hasSize(1); + List lNodes = scl.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0).getFunction().get(0).getLNode(); + assertThat(lNodes) + .hasSize(4) + .extracting(TLNode::getIedName) + .containsExactly("iedName1", "iedName2", "iedName3", "iedName4"); + assertThat(lNodes.subList(1, 4)).allSatisfy( + tlNode -> assertThat(tlNode) + .hasFieldOrPropertyWithValue("lnClass", List.of("LPHD")) + .hasFieldOrPropertyWithValue("ldInst", "ldInst1") + .hasFieldOrPropertyWithValue("lnInst", "1") + .hasFieldOrPropertyWithValue("lnType", "lnType1")); + assertThat(lNodes.subList(1, 4)).allSatisfy(tlNode -> + assertThat(tlNode.getPrivate()) + .isNotEmpty() + .allSatisfy(tPrivate -> assertThat(PrivateService.getCompasICDHeader(tPrivate)).isPresent())); + assertIsMarshallable(scl); + } + + @Test + void updateLNodeIEDNames_when_private_is_missing_should_throw_exception() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/scd-with-substation-lnode.xml"); + List lNodes = scl.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0).getFunction().get(0).getLNode(); + lNodes.get(0).unsetPrivate(); + // When & Then + assertThatThrownBy(() -> SubstationService.updateLNodeIEDNames(scl)).isInstanceOf(ScdException.class) + .hasMessage(XPATH_FUNCTION_BAY_1_TDCL + " doesn't contain any Private/compas:ICDHeader"); + } + + @Test + void updateLNodeIEDNames_when_private_is_empty_should_throw_exception() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/scd-with-substation-lnode.xml"); + List lNodes = scl.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0).getFunction().get(0).getLNode(); + lNodes.get(0).getPrivate().clear(); + // When & Then + assertThatThrownBy(() -> SubstationService.updateLNodeIEDNames(scl)).isInstanceOf(ScdException.class) + .hasMessage(XPATH_FUNCTION_BAY_1_TDCL + " doesn't contain any" + + " Private/compas:ICDHeader");; + } + + @Test + void updateLNodeIEDNames_when_private_iedName_is_empty_should_throw_exception() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/scd-with-substation-lnode.xml"); + TLNode lNode = scl.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0).getFunction().get(0).getLNode().get(0); + PrivateService.getCompasPrivates(lNode, TCompasICDHeader.class).get(0).setIEDName(""); + // When & Then + assertThatThrownBy(() -> SubstationService.updateLNodeIEDNames(scl)).isInstanceOf(ScdException.class) + .hasMessage(XPATH_LNODE_RADR + "/Private/compas:ICDHeader/@IEDName is missing or is blank");; + } + + @Test + void updateLNodeIEDNames_when_private_iedName_is_missing_should_throw_exception() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/scd-with-substation-lnode.xml"); + TLNode lNode = scl.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0).getFunction().get(0).getLNode().get(0); + List compasPrivates = PrivateService.getCompasPrivates(lNode, TCompasICDHeader.class); + assertThat(compasPrivates).hasSize(1); + compasPrivates.get(0).setIEDName(null); + // When & Then + assertThatThrownBy(() -> SubstationService.updateLNodeIEDNames(scl)).isInstanceOf(ScdException.class) + .hasMessage(XPATH_LNODE_RADR + "/Private/compas:ICDHeader/@IEDName is missing or is blank");; + } + + @Test + void updateLNodeIEDNames_when_private_iedName_is_missing_and_has_multiple_privates_should_throw_exception() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/scd-with-substation-lnode.xml"); + TLNode lNode = scl.getSubstation().get(0).getVoltageLevel().get(0).getBay().get(0).getFunction().get(0).getLNode().get(1); + List compasPrivates = PrivateService.getCompasPrivates(lNode, TCompasICDHeader.class); + assertThat(compasPrivates).hasSize(3); + compasPrivates.get(0).setIEDName(null); + // When & Then + assertThatThrownBy(() -> SubstationService.updateLNodeIEDNames(scl)).isInstanceOf(ScdException.class) + .hasMessage(XPATH_FUNCTION_BAY_1_TDCL + "/LNode[@iedName=\"None\" and @ldInst=\"ldInst1\" and @Prefix=\"prefix1\" and @lnClass=\"LPHD\" and @lnInst=\"1\"]/Private/compas:ICDHeader/@IEDName is missing or is blank");; + } + +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapterTest.java index f31403f39..5fca85bf4 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapterTest.java @@ -367,6 +367,6 @@ void addPrivate() throws Exception { TPrivate tPrivate = new TPrivate(); tPrivate.setType("Private Type"); tPrivate.setSource("Private Source"); - assertThrows(IllegalArgumentException.class, () -> dttAdapter.addPrivate(tPrivate)); + assertThrows(UnsupportedOperationException.class, () -> dttAdapter.addPrivate(tPrivate)); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/header/HeaderAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/header/HeaderAdapterTest.java index 8901c4487..7c7597891 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/header/HeaderAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/header/HeaderAdapterTest.java @@ -66,7 +66,7 @@ void addPrivate() throws Exception { TPrivate tPrivate = new TPrivate(); tPrivate.setType("Private Type"); tPrivate.setSource("Private Source"); - assertThrows(IllegalArgumentException.class, () -> hAdapter.addPrivate(tPrivate)); + assertThrows(UnsupportedOperationException.class, () -> hAdapter.addPrivate(tPrivate)); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/BayAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/BayAdapterTest.java index 9acc23cc2..e36aab2c9 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/BayAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/BayAdapterTest.java @@ -6,13 +6,12 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.lfenergy.compas.scl2007b4.model.TBay; -import org.lfenergy.compas.scl2007b4.model.TPrivate; -import org.lfenergy.compas.scl2007b4.model.TSubstation; -import org.lfenergy.compas.scl2007b4.model.TVoltageLevel; +import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import java.util.stream.Stream; + import static org.junit.jupiter.api.Assertions.*; class BayAdapterTest { @@ -34,6 +33,7 @@ public void init() throws ScdException { vLevelAdapter = ssAdapter.getVoltageLevelAdapter("VOLTAGE_LEVEL").get(); TBay tBay = new TBay(); tBay.setName("BAY"); + tBay.getFunction().add(new TFunction()); vLevelAdapter.getCurrentElem().getBay().add(tBay); bayAdapter = vLevelAdapter.getBayAdapter("BAY").get(); @@ -74,4 +74,32 @@ void addPrivate() { bayAdapter.addPrivate(tPrivate); assertEquals(1, bayAdapter.getCurrentElem().getPrivate().size()); } -} \ No newline at end of file + + @Test + void elementXPath_should_succeed() { + // Given : init + // When + String result = bayAdapter.elementXPath(); + // Then + assertEquals("Bay[@name=\"BAY\"]", result); + } + + @Test + void elementXPath_when_name_is_missing_should_succeed() { + // Given : init + bayAdapter.getCurrentElem().setName(null); + // When + String result = bayAdapter.elementXPath(); + // Then + assertEquals("Bay[not(@name)]", result); + } + + @Test + void streamFunctionAdapters() { + // Given : init + // When + Stream result = bayAdapter.streamFunctionAdapters(); + // Then + assertEquals(1, result.count()); + } +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/FunctionAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/FunctionAdapterTest.java new file mode 100644 index 000000000..c213fffa3 --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/FunctionAdapterTest.java @@ -0,0 +1,109 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.scl.sstation; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.TBay; +import org.lfenergy.compas.scl2007b4.model.TCompasICDHeader; +import org.lfenergy.compas.scl2007b4.model.TFunction; +import org.lfenergy.compas.scl2007b4.model.TLNode; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.PrivateService; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class FunctionAdapterTest { + + private FunctionAdapter functionAdapter; + + @BeforeEach + void setUp() { + TBay tBay = new TBay(); + BayAdapter bayAdapter = new BayAdapter(null, tBay); + TFunction tFunction = new TFunction(); + tFunction.setName("functionName"); + tBay.getFunction().add(tFunction); + functionAdapter = new FunctionAdapter(bayAdapter, tFunction); + } + + @Test + void amChildElementRef_should_succeed() { + // Given : setUp + // When + boolean result = functionAdapter.amChildElementRef(); + // Then + assertThat(result).isTrue(); + } + + @Test + void amChildElementRef_when_parent_does_not_contain_function_should_be_false() { + // Given : setUp + functionAdapter.getParentAdapter().getCurrentElem().getFunction().clear(); + // When + boolean result = functionAdapter.amChildElementRef(); + // Then + assertThat(result).isFalse(); + } + + @Test + void elementXPath() { + // Given : setUp + // When + String result = functionAdapter.elementXPath(); + // Then + assertThat(result).isEqualTo("Function[@name=\"functionName\"]"); + } + + @Test + void updateLNodeIedNames_when_one_private_should_succeed() { + // Given + TLNode tlNode = new TLNode(); + TCompasICDHeader tCompasICDHeader = new TCompasICDHeader(); + tCompasICDHeader.setIEDName("iedName1"); + tlNode.getPrivate().add(PrivateService.createPrivate(tCompasICDHeader)); + functionAdapter.getCurrentElem().getLNode().add(tlNode); + // When + functionAdapter.updateLNodeIedNames(); + // Then + assertThat(functionAdapter.getCurrentElem().getLNode()) + .hasSize(1) + .map(TLNode::getIedName).containsExactly("iedName1"); + } + + @Test + void updateLNodeIedNames_when_multiples_privates_should_succeed() { + // Given + TLNode tlNode = new TLNode(); + TCompasICDHeader tCompasICDHeader1 = new TCompasICDHeader(); + tCompasICDHeader1.setIEDName("iedName1"); + TCompasICDHeader tCompasICDHeader2 = new TCompasICDHeader(); + tCompasICDHeader2.setIEDName("iedName2"); + TCompasICDHeader tCompasICDHeader3 = new TCompasICDHeader(); + tCompasICDHeader3.setIEDName("iedName3"); + tlNode.getPrivate().add(PrivateService.createPrivate(tCompasICDHeader1)); + tlNode.getPrivate().add(PrivateService.createPrivate(tCompasICDHeader2)); + tlNode.getPrivate().add(PrivateService.createPrivate(tCompasICDHeader3)); + functionAdapter.getCurrentElem().getLNode().add(tlNode); + // When + functionAdapter.updateLNodeIedNames(); + // Then + assertThat(functionAdapter.getCurrentElem().getLNode()) + .hasSize(3) + .map(TLNode::getIedName) + .containsExactly("iedName1", "iedName2", "iedName3"); + } + + @Test + void updateLNodeIedNames_when_no_private_should_throw_exception() { + // Given + TLNode tlNode = new TLNode(); + functionAdapter.getCurrentElem().getLNode().add(tlNode); + // When & Then + assertThatThrownBy(() -> functionAdapter.updateLNodeIedNames()).isInstanceOf(ScdException.class); + } + +} 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 new file mode 100644 index 000000000..7429cfdca --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/sstation/LNodeAdapterTest.java @@ -0,0 +1,111 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.scl.sstation; + +import org.junit.jupiter.api.Test; +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 javax.xml.bind.JAXBElement; +import javax.xml.namespace.QName; +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class LNodeAdapterTest { + + @Test + void constructor_should_create_LNode_with_no_parents() { + // Given + TLNode tlNode = new TLNode(); + // When + LNodeAdapter lNodeAdapter = new LNodeAdapter(null, tlNode); + // Then + assertThat(lNodeAdapter.getParentAdapter()).isNull(); + } + + @Test + void constructor_when_LNode_is_child_of_parent_should_succeed() { + // Given + TLNode tlNode = new TLNode(); + TFunction tFunction = new TFunction(); + tFunction.getLNode().add(tlNode); + FunctionAdapter functionAdapter = new FunctionAdapter(null, tFunction); + // When + LNodeAdapter lNodeAdapter = new LNodeAdapter(functionAdapter, tlNode); + // Then + assertThat(lNodeAdapter.getParentAdapter()).isNotNull(); + } + + @Test + void constructor_when_LNode_is_not_child_of_parent_should_throw_exception() { + // Given + TLNode tlNode = new TLNode(); + TFunction tFunction = new TFunction(); + FunctionAdapter functionAdapter = new FunctionAdapter(null, tFunction); + // When & Then + assertThatThrownBy(() -> new LNodeAdapter(functionAdapter, tlNode)).isInstanceOf(IllegalArgumentException.class); + } + + @Test + void addPrivate_should_succeed() { + // Given + TLNode tlNode = new TLNode(); + LNodeAdapter lNodeAdapter = new LNodeAdapter(null, tlNode); + TPrivate tPrivate = PrivateService.createPrivate(TCompasSclFileType.SCD); + // When + lNodeAdapter.addPrivate(tPrivate); + // Then + assertThat(tlNode.getPrivate()).hasSize(1); + assertThat(tlNode.getPrivate().get(0).getContent()).hasSize(1).first().isInstanceOf(JAXBElement.class); + JAXBElement jaxbElement = (JAXBElement) tlNode.getPrivate().get(0).getContent().get(0); + assertThat(jaxbElement.getValue()).isEqualTo(TCompasSclFileType.SCD); + } + + @Test + void deepCopy_should_succeed() { + // Given + TLNode tlNode = new TLNode(); + tlNode.setIedName("iedName1"); + tlNode.setLdInst("ldInst1"); + tlNode.setPrefix("prefix1"); + tlNode.getLnClass().add("lnClass1"); + tlNode.setLnInst("lnInst1"); + tlNode.setLnType("lnType1"); + tlNode.setDesc("Desc1"); + tlNode.getAny().add("any1"); + TText tText = new ObjectFactory().createTText(); + tText.setSource("Text1"); + tText.getContent().add("Text1"); + tText.getOtherAttributes().put(QName.valueOf("Text1_attribute1"), "Text1_value1"); + tlNode.setText(tText); + tlNode.getPrivate().add(PrivateService.createPrivate(TCompasSclFileType.SCD)); + tlNode.getOtherAttributes().put(QName.valueOf("tlNode_attribute1"), "tlNode_value1"); + LNodeAdapter lNodeAdapter = new LNodeAdapter(null, tlNode); + // When + TLNode result = lNodeAdapter.deepCopy(); + // Then + assertThat(result).usingRecursiveComparison().isEqualTo(tlNode); + List fields = ReflectionSupport.findFields(TLNode.class, field -> true, HierarchyTraversalMode.BOTTOM_UP); + assertThat(fields).isNotEmpty().allSatisfy( + field -> { + Optional optionalValue = ReflectionSupport.tryToReadFieldValue(field, result).toOptional(); + assertThat(optionalValue).isPresent(); + Object value = optionalValue.get(); + if (value instanceof Collection) { + assertThat((Collection) value).isNotEmpty(); + } else { + assertThat(value).isNotNull(); + } + } + ); + } +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/MarshallerWrapper.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/MarshallerWrapper.java index 92fb85aa0..3e61a8b87 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/MarshallerWrapper.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/MarshallerWrapper.java @@ -41,7 +41,7 @@ public String marshall(final T obj) { return sw.toString(); } catch (JAXBException exp) { String message = String.format("Error marshalling the Class: %s", exp); - log.error(message); + log.error(message, exp); throw new CompasException(CompasErrorCode.MARSHAL_ERROR_CODE, message); } } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclTestMarshaller.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclTestMarshaller.java index 98594458b..ac80d9ddb 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclTestMarshaller.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclTestMarshaller.java @@ -22,7 +22,7 @@ public static String assertIsMarshallable(SCL scl) { return assertDoesNotThrow(() -> marshallerWrapper.marshall(scl)); } - public static MarshallerWrapper createWrapper() { + private static MarshallerWrapper createWrapper() { return MarshallerWrapper.builder() .withProperties("classpath:scl_schema.yml") .build(); diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/CommonConstantsTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/CommonConstantsTest.java new file mode 100644 index 000000000..d4930c0df --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/CommonConstantsTest.java @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.util; + +import org.junit.jupiter.api.Test; +import org.junit.platform.commons.support.ReflectionSupport; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class CommonConstantsTest { + + @Test + void constructor_should_throw_exception() { + // Given + // When & Then + assertThatThrownBy(() -> ReflectionSupport.newInstance(Utils.class)) + .isInstanceOf(UnsupportedOperationException.class); + } + +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/PrivateEnumTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/PrivateEnumTest.java new file mode 100644 index 000000000..0a0b59a3e --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/PrivateEnumTest.java @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.util; + +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.TCompasSclFileType; + +import java.util.NoSuchElementException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class PrivateEnumTest { + + @Test + void fromClass_should_return_PrivateEnum() { + // Given + Class compasClass = TCompasSclFileType.class; + // When + PrivateEnum result = PrivateEnum.fromClass(compasClass); + // Then + assertThat(result).isEqualTo(PrivateEnum.COMPAS_SCL_FILE_TYPE); + } + + @Test + void fromClass_with_unknown_class_should_throw_exception() { + // Given + Class classToTest = Object.class; + // When & Then + assertThatThrownBy(() -> PrivateEnum.fromClass(classToTest)).isInstanceOf(NoSuchElementException.class); + } + + @Test + void toString_should_return_private_type() { + // Given + PrivateEnum privateEnum = PrivateEnum.COMPAS_SCL_FILE_TYPE; + // When + String result = privateEnum.toString(); + // Then + assertThat(result).isEqualTo("COMPAS-SclFileType"); + } + +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/UtilsTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/UtilsTest.java similarity index 54% rename from sct-commons/src/test/java/org/lfenergy/compas/sct/commons/UtilsTest.java rename to sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/UtilsTest.java index 243b2f36b..24ea812f3 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/UtilsTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/UtilsTest.java @@ -2,17 +2,30 @@ // // SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons; +package org.lfenergy.compas.sct.commons.util; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.platform.commons.support.ReflectionSupport; -import java.util.NoSuchElementException; -import java.util.Optional; +import java.util.*; +import java.util.stream.Stream; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; + class UtilsTest { + @Test + void constructor_should_throw_exception() { + // Given + // When & Then + assertThatThrownBy(() -> ReflectionSupport.newInstance(Utils.class)) + .isInstanceOf(UnsupportedOperationException.class); + } + @Test void entering_should_return_text() { // Given : method name @@ -52,7 +65,7 @@ void leaving_should_return_text_with_invalid_time() { @Test void equalsOrNotSet_should_return_true_when_both_values_are_not_set() { // Given - Optional object1= Optional.empty(); + Optional object1 = Optional.empty(); Optional object2 = Optional.empty(); // When boolean result1 = Utils.equalsOrNotSet(object1, object2, Optional::isPresent, Optional::get); @@ -65,7 +78,7 @@ void equalsOrNotSet_should_return_true_when_both_values_are_not_set() { @Test void equalsOrNotSet_should_return_true_when_both_values_are_set_and_equal() { // Given - Optional object1= Optional.of(1L); + Optional object1 = Optional.of(1L); Optional object2 = Optional.of(1L); // When boolean result1 = Utils.equalsOrNotSet(object1, object2, Optional::isPresent, Optional::get); @@ -78,7 +91,7 @@ void equalsOrNotSet_should_return_true_when_both_values_are_set_and_equal() { @Test void equalsOrNotSet_should_return_false_when_both_values_are_set_but_differ() { // Given - Optional object1= Optional.of(1L); + Optional object1 = Optional.of(1L); Optional object2 = Optional.of(2L); // When boolean result1 = Utils.equalsOrNotSet(object1, object2, Optional::isPresent, Optional::get); @@ -91,7 +104,7 @@ void equalsOrNotSet_should_return_false_when_both_values_are_set_but_differ() { @Test void equalsOrNotSet_should_return_false_when_one_is_set_and_the_other_is_not() { // Given - Optional object1= Optional.of(1L); + Optional object1 = Optional.of(1L); Optional object2 = Optional.empty(); // When boolean result1 = Utils.equalsOrNotSet(object1, object2, Optional::isPresent, Optional::get); @@ -104,11 +117,74 @@ void equalsOrNotSet_should_return_false_when_one_is_set_and_the_other_is_not() { @Test void equalsOrNotSet_should_throw_exception_when_value_is_null_and_isSet_is_misleading() { // Given - Optional object1= Optional.of(1L); + Optional object1 = Optional.of(1L); Optional object2 = Optional.empty(); // When & Then assertThrows(NoSuchElementException.class, () -> Utils.equalsOrNotSet(object1, object2, o -> true, Optional::get)); assertThrows(NoSuchElementException.class, () -> Utils.equalsOrNotSet(object2, object1, o -> true, Optional::get)); } + @Test + void xpathAttributeFilter_should_succeed() { + // Given + String attributeName = "name"; + String attributeValue = "value"; + // When + String result = Utils.xpathAttributeFilter(attributeName, attributeValue); + // Then + assertEquals("@name=\"value\"", result); + } + + @Test + void xpathAttributeFilter_when_value_is_null_should_succeed() { + // Given + String attributeName = "name"; + String attributeValue = null; + // When + String result = Utils.xpathAttributeFilter(attributeName, attributeValue); + // Then + assertEquals("not(@name)", result); + } + + @Test + void xpathAttributeFilter_when_value_is_collection_should_succeed() { + // Given + String attributeName = "name"; + List attributeValue = List.of("value1", "value2"); + // When + String result = Utils.xpathAttributeFilter(attributeName, attributeValue); + // Then + assertEquals("@name=\"value1 value2\"", result); + } + + @Test + void xpathAttributeFilter_when_value_is_collection_should_ignore_null_values() { + // Given + String attributeName = "name"; + List attributeValue = Arrays.asList(null, "value1", "value2"); + // When + String result = Utils.xpathAttributeFilter(attributeName, attributeValue); + // Then + assertEquals("@name=\"value1 value2\"", result); + } + + @ParameterizedTest + @MethodSource("xpathAttributeFilterEmptyCollectionSource") + void xpathAttributeFilter_when_empty_collection_should_succeed(Collection attributeValue) { + // Given + String attributeName = "name"; + // When + String result = Utils.xpathAttributeFilter(attributeName, attributeValue); + // Then + assertEquals("not(@name)", result); + } + + public static Stream> xpathAttributeFilterEmptyCollectionSource() { + return Stream.of( + null, + Collections.emptyList(), + Arrays.asList(new String[1]), + Arrays.asList(new String[5]) + ); + } } diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/scd-with-substation-lnode.xml b/sct-commons/src/test/resources/scd-refresh-lnode/scd-with-substation-lnode.xml new file mode 100644 index 000000000..59865ec48 --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/scd-with-substation-lnode.xml @@ -0,0 +1,31 @@ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +