diff --git a/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java b/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java index 33ab8ce65..505349145 100644 --- a/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java +++ b/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceIntegrationTest.java @@ -32,7 +32,7 @@ class SclAutomationServiceIntegrationTest { private SclAutomationService sclAutomationService ; private static final SclEditor sclEditor = new SclService() ; private static final SubstationEditor substationEditor = new SubstationService(new VoltageLevelService()) ; - private static final ControlBlockEditor controlBlockEditor = new ControlBlockEditorService(new ControlService(), new LdeviceService()) ; + private static final ControlBlockEditor controlBlockEditor = new ControlBlockEditorService(new ControlService(), new LdeviceService(new LnService())); private HeaderDTO headerDTO; diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java index 94593fdd7..d8e914d37 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/ExtRefEditorService.java @@ -54,7 +54,7 @@ public class ExtRefEditorService implements ExtRefEditor { * @param channel TChannel represent parameters * @return the IED sources matching the LDEPF parameters */ - private static List getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compasBay, TChannel channel) { + private List getIedSources(SclRootAdapter sclRootAdapter, TCompasBay compasBay, TChannel channel) { return sclRootAdapter.streamIEDAdapters() .filter(iedAdapter -> (channel.getBayScope().equals(TCBScopeType.BAY_EXTERNAL) && iedAdapter.getPrivateCompasBay().stream().noneMatch(bay -> bay.getUUID().equals(compasBay.getUUID()))) @@ -143,8 +143,7 @@ private static boolean doesIcdHeaderMatchLDEPFChannel(IEDAdapter iedAdapter, TCh * @param channel TChannel * @return LDeviceAdapter object that matches the EPF channel */ - private static Optional getActiveSourceLDeviceByLDEPFChannel(IEDAdapter iedAdapter, TChannel channel) { - LdeviceService ldeviceService = new LdeviceService(); + private Optional getActiveSourceLDeviceByLDEPFChannel(IEDAdapter iedAdapter, TChannel channel) { return ldeviceService.findLdevice(iedAdapter.getCurrentElem(), tlDevice -> tlDevice.getInst().equals(channel.getLDInst())) .filter(tlDevice -> ldeviceService.getLdeviceStatus(tlDevice).map(ActiveStatus.ON::equals).orElse(false)) .map(tlDevice -> new LDeviceAdapter(iedAdapter, tlDevice)); diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/LdeviceService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/LdeviceService.java index 008aad426..d2eefaf84 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/LdeviceService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/LdeviceService.java @@ -4,7 +4,11 @@ package org.lfenergy.compas.sct.commons; -import org.lfenergy.compas.scl2007b4.model.*; +import lombok.RequiredArgsConstructor; +import org.lfenergy.compas.scl2007b4.model.TAccessPoint; +import org.lfenergy.compas.scl2007b4.model.TIED; +import org.lfenergy.compas.scl2007b4.model.TLDevice; +import org.lfenergy.compas.scl2007b4.model.TServer; import org.lfenergy.compas.sct.commons.util.ActiveStatus; import java.util.Objects; @@ -12,8 +16,11 @@ import java.util.function.Predicate; import java.util.stream.Stream; +@RequiredArgsConstructor public class LdeviceService { + private final LnService lnService; + public Stream getLdevices(TIED tied) { if (!tied.isSetAccessPoint()) { return Stream.empty(); @@ -40,7 +47,6 @@ public Optional findLdevice(TIED tied, Predicate ldevicePred } public Optional getLdeviceStatus(TLDevice tlDevice) { - LnService lnService = new LnService(); - return lnService.getDaiModStval(tlDevice.getLN0()); + return lnService.getDaiModStValValue(tlDevice.getLN0()); } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/LnService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/LnService.java index ba06e5f7e..74aef2e46 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/LnService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/LnService.java @@ -12,7 +12,6 @@ import org.lfenergy.compas.sct.commons.util.ActiveStatus; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.function.Predicate; @@ -25,6 +24,8 @@ @Slf4j public class LnService implements LnEditor { + private static final DoLinkedToDaFilter DAI_FILTER_MOD_STVAL = DoLinkedToDaFilter.from(MOD_DO_NAME, STVAL_DA_NAME); + public Stream getAnylns(TLDevice tlDevice) { return Stream.concat(Stream.of(tlDevice.getLN0()), tlDevice.getLN().stream()); } @@ -60,33 +61,29 @@ public Optional findLn(TLDevice tlDevice, Predicate lnPredicate) { * @return the Lnode Status */ public ActiveStatus getLnStatus(TAnyLN tAnyLN, LN0 ln0) { - Optional ln0Status = getDaiModStval(ln0); - return getDaiModStval(tAnyLN).filter(ActiveStatus.OFF::equals).orElseGet(() -> ln0Status.orElse(ActiveStatus.OFF)); + Optional ln0Status = getDaiModStValValue(ln0); + return getDaiModStValValue(tAnyLN).filter(ActiveStatus.OFF::equals).orElseGet(() -> ln0Status.orElse(ActiveStatus.OFF)); } - public Optional getDaiModStval(TAnyLN tAnyLN) { - return tAnyLN - .getDOI() + public Optional getDaiModStValValue(TAnyLN tAnyLN) { + return getDaiModStVal(tAnyLN) .stream() - .filter(tdoi -> MOD_DO_NAME.equals(tdoi.getName())) + .flatMap(tdai -> tdai.getVal().stream()) + .map(TVal::getValue) .findFirst() - .flatMap(tdoi -> tdoi.getSDIOrDAI() - .stream() - .filter(dai -> dai.getClass().equals(TDAI.class)) - .map(TDAI.class::cast) - .filter(tdai -> STVAL_DA_NAME.equals(tdai.getName())) - .map(TDAI::getVal) - .flatMap(Collection::stream) - .findFirst() - .map(TVal::getValue)) .map(ActiveStatus::fromValue); } + + public Optional getDaiModStVal(TAnyLN tAnyLN) { + return getDOAndDAInstances(tAnyLN, DAI_FILTER_MOD_STVAL); + } + public Stream getActiveLns(TLDevice tlDevice) { LN0 ln0 = tlDevice.getLN0(); Stream tlnStream = tlDevice.getLN() .stream() .filter(tln -> ActiveStatus.ON.equals(getLnStatus(tln, ln0))); - Stream ln0Stream = Stream.of(ln0).filter(ln02 -> getDaiModStval(ln02).map(ActiveStatus.ON::equals).orElse(false)); + Stream ln0Stream = Stream.of(ln0).filter(ln02 -> getDaiModStValValue(ln02).map(ActiveStatus.ON::equals).orElse(false)); return Stream.concat(ln0Stream, tlnStream); } @@ -99,7 +96,7 @@ public Optional getDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDaFilter doLi return tAnyLN.getDOI().stream().filter(doi -> doi.getName().equals(doLinkedToDaFilter.doName())) .findFirst() .flatMap(doi -> { - if(structNamesList.size() > 1) { + if (structNamesList.size() > 1) { String firstSDIName = structNamesList.removeFirst(); return this.getSdiByName(doi, firstSDIName) .map(intermediateSdi -> findSDIByStructName(intermediateSdi, structNamesList)) @@ -116,7 +113,7 @@ public Optional getDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDaFilter doLi return Optional.empty(); }) .stream().findFirst(); - } else if(structNamesList.size() == 1){ + } else if (structNamesList.size() == 1) { return doi.getSDIOrDAI().stream() .filter(unNaming -> unNaming.getClass().equals(TDAI.class)) .map(TDAI.class::cast) @@ -138,7 +135,7 @@ public void updateOrCreateDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDa doLinkedT .ifPresentOrElse(tVal -> tVal.setValue(value), () -> tdai.getVal().add(newVal(value))); } else { - for (DaVal daVal: daiVals) { + for (DaVal daVal : daiVals) { tdai.getVal().stream() .filter(tValElem -> tValElem.isSetSGroup() && tValElem.getSGroup() == daVal.settingGroup()) .findFirst() @@ -198,22 +195,22 @@ private Optional createDoiSdiDaiChainIfNotExists(TAnyLN tAnyLN, DataObject TDOI doi = tAnyLN.getDOI().stream().filter(doi1 -> doi1.getName().equals(dataObject.getDoName())) .findFirst() - .orElseGet(()-> { + .orElseGet(() -> { TDOI newDOI = new TDOI(); newDOI.setName(dataObject.getDoName()); tAnyLN.getDOI().add(newDOI); return newDOI; }); - if(structInstances.size() > 1){ + if (structInstances.size() > 1) { TSDI firstSDI = findOrCreateSDIFromDOI(doi, structInstances.getFirst()); TSDI lastSDI = findOrCreateSDIByStructName(firstSDI, structInstances); - if(structInstances.size() == 1){ + if (structInstances.size() == 1) { return lastSDI.getSDIOrDAI().stream() .filter(tUnNaming -> tUnNaming.getClass().equals(TDAI.class)) .map(TDAI.class::cast) .filter(tdai -> tdai.getName().equals(structInstances.getFirst())) .map(tdai -> { - if(tdai.isSetValImport()) { + if (tdai.isSetValImport()) { tdai.setValImport(dataAttribute.isValImport()); } return tdai; @@ -226,13 +223,13 @@ private Optional createDoiSdiDaiChainIfNotExists(TAnyLN tAnyLN, DataObject return Optional.of(newDAI); }); } - } else if(structInstances.size() == 1){ + } else if (structInstances.size() == 1) { return doi.getSDIOrDAI().stream() .filter(tUnNaming -> tUnNaming.getClass().equals(TDAI.class)) .map(TDAI.class::cast) .filter(tdai -> tdai.getName().equals(structInstances.getFirst())) .map(tdai -> { - if(tdai.isSetValImport()) tdai.setValImport(dataAttribute.isValImport()); + if (tdai.isSetValImport()) tdai.setValImport(dataAttribute.isValImport()); return tdai; }) .findFirst() @@ -247,7 +244,7 @@ private Optional createDoiSdiDaiChainIfNotExists(TAnyLN tAnyLN, DataObject } private TSDI findSDIByStructName(TSDI tsdi, List sdiNames) { - if(sdiNames.isEmpty()) return tsdi; + if (sdiNames.isEmpty()) return tsdi; return this.getSdiByName(tsdi, sdiNames.getFirst()) .map(sdi1 -> { sdiNames.removeFirst(); @@ -294,14 +291,13 @@ private Optional getSdiByName(TSDI sdi, String sdiName) { } /** - * - * @param sdi TSDI + * @param sdi TSDI * @param structName list start with sdi name * @return already existing TSDI or newly created TSDI from given TSDI */ private TSDI findOrCreateSDIByStructName(TSDI sdi, List structName) { structName.removeFirst(); - if(structName.isEmpty() || structName.size() == 1) return sdi; + if (structName.isEmpty() || structName.size() == 1) return sdi; return findOrCreateSDIByStructName(findOrCreateSDIFromSDI(sdi, structName.getFirst()), structName); } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/LnEditor.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/LnEditor.java index 889433c17..84b9d6881 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/LnEditor.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/api/LnEditor.java @@ -8,11 +8,16 @@ import org.lfenergy.compas.scl2007b4.model.TDAI; import org.lfenergy.compas.sct.commons.domain.DoLinkedToDa; import org.lfenergy.compas.sct.commons.domain.DoLinkedToDaFilter; +import org.lfenergy.compas.sct.commons.util.ActiveStatus; import java.util.Optional; public interface LnEditor { + Optional getDaiModStValValue(TAnyLN tAnyLN); + + Optional getDaiModStVal(TAnyLN tAnyLN); + Optional getDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDaFilter doLinkedToDaFilter); void updateOrCreateDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDa doLinkedToDa); 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 ecc3986cf..6d1823765 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 @@ -8,17 +8,20 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.scl2007b4.model.TAnyLN; +import org.lfenergy.compas.scl2007b4.model.TExtRef; +import org.lfenergy.compas.scl2007b4.model.TLNodeType; import org.lfenergy.compas.sct.commons.DataSetService; import org.lfenergy.compas.sct.commons.ExtRefReaderService; import org.lfenergy.compas.sct.commons.LnodeTypeService; 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.ln.AbstractLNAdapter; import org.lfenergy.compas.sct.commons.scl.ldevice.LDeviceAdapter; +import org.lfenergy.compas.sct.commons.scl.ln.AbstractLNAdapter; import org.lfenergy.compas.sct.commons.scl.ln.LNAdapter; -import org.lfenergy.compas.sct.commons.scl.ln.LnKey; +import org.lfenergy.compas.sct.commons.scl.ln.LnId; import org.lfenergy.compas.sct.commons.util.Utils; import java.util.HashSet; @@ -152,14 +155,10 @@ public static LNodeDTO from(AbstractLNAdapter nodeAdapter, public static LNodeDTO from(TAnyLN tAnyLN, LogicalNodeOptions options, String iedName, String ldInst, SCL scl) { log.info(Utils.entering()); - LnKey lnKey = switch (tAnyLN) { - case LN0 ln0 -> new LnKey(ln0); - case TLN tln -> new LnKey(tln); - default -> throw new IllegalStateException("Unexpected value: " + tAnyLN); - }; - String inst = lnKey.getInst(); - String lnClass = lnKey.getLnClass(); - String prefix = lnKey.getPrefix(); + LnId lnId = LnId.from(tAnyLN); + String inst = lnId.lnInst(); + String lnClass = lnId.lnClass(); + String prefix = lnId.prefix(); String lnType = tAnyLN.getLnType(); LNodeDTO lNodeDTO = new LNodeDTO(inst, lnClass, prefix, lnType); if (options.isWithExtRef()) { diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ln/LnId.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ln/LnId.java new file mode 100644 index 000000000..d8aedebba --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ln/LnId.java @@ -0,0 +1,81 @@ +// SPDX-FileCopyrightText: 2025 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 +package org.lfenergy.compas.sct.commons.scl.ln; + +import org.apache.commons.lang3.StringUtils; +import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; + +import java.util.List; +import java.util.Objects; + +public record LnId(String lnClass, String lnInst, String prefix) { + private static final String LN0_LNCLASS = TLLN0Enum.LLN_0.value(); + + /** + * Id of LN0. All LN0 have the same lnClass, lnInst and prefix in SCD + */ + public static final LnId LN0_ID = new LnId(LN0_LNCLASS, "", ""); + + /** + * Constructor + * + * @param lnClass always required + * @param lnInst optional. It should be empty for LN0, and should be filled for LN. No verification is done because some Lnode GAPC do not have a lninst. + * @param prefix optional. Is set to empty if null because empty is the default value on LN and the majority of the JAXB Element (LN, LNode, FCDA, ClientLN, but not on ExtRef and IEDName unfortunately) + */ + public LnId(String lnClass, String lnInst, String prefix) { + if (StringUtils.isBlank(lnClass)) { + throw new ScdException("lnClass is required"); + } + this.lnClass = lnClass; + this.lnInst = Objects.requireNonNullElse(lnInst, ""); + this.prefix = Objects.requireNonNullElse(prefix, ""); + } + + /** + * Alternative constructor with lnClass as a List instead of a String. + * JAXB classes lnClass attribute are List, even though it can only contain one element. + * This constructor makes it easier to create LnId from JAXB classes + * + * @param lnClass one element list containing the lnClass value of the LN + * @param lnInst LN lnInst + * @param prefix LN prefix + */ + public LnId(List lnClass, String lnInst, String prefix) { + this(lnClass == null || lnClass.isEmpty() ? null : lnClass.getFirst(), lnInst, prefix); + } + + /** + * Extract id from LN element + * + * @param tAnyLN LN element + * @return id + */ + public static LnId from(TAnyLN tAnyLN) { + if (tAnyLN instanceof TLN0) { + return LN0_ID; + } else if (tAnyLN instanceof TLN tln) { + return new LnId(tln.getLnClass(), tln.getInst(), tln.getPrefix()); + } else { + throw new ScdException("Unexpected class : " + (tAnyLN != null ? tAnyLN.getClass() : null)); + } + } + + /** + * Extract id from LNode element + * + * @param tlNode LNode element + * @return id + */ + public static LnId from(TLNode tlNode) { + if (tlNode.getLnClass().contains(LN0_LNCLASS)) { + return LN0_ID; + } else { + return new LnId(tlNode.getLnClass(), tlNode.getLnInst(), tlNode.getPrefix()); + } + } + + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ln/LnKey.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ln/LnKey.java deleted file mode 100644 index 3f37c514f..000000000 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ln/LnKey.java +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-FileCopyrightText: 2021 RTE FRANCE -// -// SPDX-License-Identifier: Apache-2.0 -package org.lfenergy.compas.sct.commons.scl.ln; - -import lombok.EqualsAndHashCode; -import lombok.Getter; -import org.apache.commons.lang3.StringUtils; -import org.lfenergy.compas.scl2007b4.model.*; - -@Getter -@EqualsAndHashCode -public class LnKey { - - private final String inst; - @EqualsAndHashCode.Exclude - private final String lnType; - private final String lnClass; - /** empty for LN0 */ - private final String prefix; - - public LnKey(LN0 ln0) { - this.inst = ln0.getInst(); - this.lnType = ln0.getLnType(); - this.lnClass = ln0.getLnClass().get(0); - this.prefix = StringUtils.EMPTY; - } - - public LnKey(TLN tln) { - this.inst = tln.getInst(); - this.lnType = tln.getLnType(); - this.lnClass = tln.getLnClass().get(0); - this.prefix = tln.getPrefix(); - } - -} - diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockEditorServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockEditorServiceTest.java index 768c1195e..316e8ed6d 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockEditorServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ControlBlockEditorServiceTest.java @@ -50,7 +50,7 @@ class ControlBlockEditorServiceTest { @BeforeEach void init() { - controlBlockEditorService = new ControlBlockEditorService(new ControlService(), new LdeviceService()); + controlBlockEditorService = new ControlBlockEditorService(new ControlService(), new LdeviceService(new LnService())); } @Test diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefEditorServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefEditorServiceTest.java index bdb7547cc..96949fe3b 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefEditorServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/ExtRefEditorServiceTest.java @@ -36,7 +36,7 @@ class ExtRefEditorServiceTest { @BeforeEach void init() { - extRefEditorService = new ExtRefEditorService(new IedService(), new LdeviceService(), new LnService(), new DataTypeTemplatesService()); + extRefEditorService = new ExtRefEditorService(new IedService(), new LdeviceService(new LnService()), new LnService(), new DataTypeTemplatesService()); } @Test diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/LdeviceServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/LdeviceServiceTest.java index 445fcf09b..051f1ce84 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/LdeviceServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/LdeviceServiceTest.java @@ -5,6 +5,7 @@ package org.lfenergy.compas.sct.commons; import org.assertj.core.groups.Tuple; +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.TIED; @@ -19,16 +20,20 @@ class LdeviceServiceTest { + private LdeviceService ldeviceService; + + @BeforeEach + void setUp() { + ldeviceService = new LdeviceService(new LnService()); + } + @Test void getLdeviceStatus_should_return_status() { //Given SCL std = SclTestMarshaller.getSCLFromFile("/std/std_sample.std"); - TLDevice tlDevice = std.getIED().get(0).getAccessPoint().get(0).getServer().getLDevice().get(0); - LdeviceService ldeviceService = new LdeviceService(); - + TLDevice tlDevice = std.getIED().getFirst().getAccessPoint().getFirst().getServer().getLDevice().getFirst(); //When Optional ldeviceStatus = ldeviceService.getLdeviceStatus(tlDevice); - //Then assertThat(ldeviceStatus).contains(ActiveStatus.ON); } @@ -37,12 +42,9 @@ void getLdeviceStatus_should_return_status() { void getLdevices_should_return_ldevices() { //Given SCL std = SclTestMarshaller.getSCLFromFile("/std/std_sample.std"); - TIED tied = std.getIED().get(0); - LdeviceService ldeviceService = new LdeviceService(); - + TIED tied = std.getIED().getFirst(); //When List tlDevices = ldeviceService.getLdevices(tied).toList(); - //Then assertThat(tlDevices) .hasSize(2) @@ -55,12 +57,9 @@ void getLdevices_should_return_ldevices() { void getFilteredLdevices_should_return_ldevices() { //Given SCL std = SclTestMarshaller.getSCLFromFile("/std/std_sample.std"); - TIED tied = std.getIED().get(0); - LdeviceService ldeviceService = new LdeviceService(); - + TIED tied = std.getIED().getFirst(); //When List tlDevices = ldeviceService.getFilteredLdevices(tied, tlDevice -> "LDTM".equals(tlDevice.getInst())).toList(); - //Then assertThat(tlDevices) .hasSize(1) @@ -72,12 +71,9 @@ void getFilteredLdevices_should_return_ldevices() { void findLdevice_should_return_ldevice() { //Given SCL std = SclTestMarshaller.getSCLFromFile("/std/std_sample.std"); - TIED tied = std.getIED().get(0); - LdeviceService ldeviceService = new LdeviceService(); - + TIED tied = std.getIED().getFirst(); //When TLDevice ldevice = ldeviceService.findLdevice(tied, tlDevice -> "LDTM".equals(tlDevice.getInst())).orElseThrow(); - //Then assertThat(ldevice) .extracting(TLDevice::getInst, TLDevice::getLdName) @@ -88,12 +84,9 @@ void findLdevice_should_return_ldevice() { void getActiveLdevices_should_return_ldevices() { //Given SCL std = SclTestMarshaller.getSCLFromFile("/std/std_sample.std"); - TIED tied = std.getIED().get(0); - LdeviceService ldeviceService = new LdeviceService(); - + TIED tied = std.getIED().getFirst(); //When List tlDevices = ldeviceService.getActiveLdevices(tied).toList(); - //Then assertThat(tlDevices) .hasSize(1) @@ -101,4 +94,4 @@ void getActiveLdevices_should_return_ldevices() { .containsExactly(Tuple.tuple("LDSUIED", "VirtualSAMULDSUIED")); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/LnServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/LnServiceTest.java index 24d3a3ebc..2c7f4bc28 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/LnServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/LnServiceTest.java @@ -121,13 +121,13 @@ void getFilteredAnyLns_should_return_lns() { } @Test - void getDaiModStval_should_return_status() { + void getDaiModStValValue_should_return_status() { //Given SCL std = SclTestMarshaller.getSCLFromFile("/std/std_sample.std"); TLDevice tlDevice = std.getIED().getFirst().getAccessPoint().getFirst().getServer().getLDevice().getFirst(); //When - Optional daiModStval = lnService.getDaiModStval(tlDevice.getLN0()); + Optional daiModStval = lnService.getDaiModStValValue(tlDevice.getLN0()); //Then assertThat(daiModStval).contains(ActiveStatus.ON); diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ln/LnIdTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ln/LnIdTest.java new file mode 100644 index 000000000..d8e17e15f --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ln/LnIdTest.java @@ -0,0 +1,69 @@ +// SPDX-FileCopyrightText: 2024 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + + +package org.lfenergy.compas.sct.commons.scl.ln; + +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.*; + +import static org.assertj.core.api.Assertions.assertThat; + +class LnIdTest { + + @Test + void from_LN_should_succeed() { + //Given + TLN ln = new TLN(); + ln.setInst("1"); + ln.getLnClass().add(TSystemLNGroupEnum.LGOS.value()); + ln.setPrefix("Prefix"); + // When + LnId lnId = LnId.from(ln); + // Then + assertThat(lnId.lnClass()).isEqualTo("LGOS"); + assertThat(lnId.lnInst()).isEqualTo("1"); + assertThat(lnId.prefix()).isEqualTo("Prefix"); + } + + @Test + void from_LN0_should_succeed() { + //Given + LN0 ln0 = new LN0(); + ln0.getLnClass().add(TLLN0Enum.LLN_0.value()); + // When + LnId lnId = LnId.from(ln0); + // Then + assertThat(lnId).isSameAs(LnId.LN0_ID); + } + + @Test + void from_TLNode_should_succeed() { + //Given + TLNode tlNode = new TLNode(); + tlNode.setLnInst("1"); + tlNode.getLnClass().add(TSystemLNGroupEnum.LGOS.value()); + tlNode.setPrefix("Prefix"); + // When + LnId lnId = LnId.from(tlNode); + // Then + assertThat(lnId.lnClass()).isEqualTo("LGOS"); + assertThat(lnId.lnInst()).isEqualTo("1"); + assertThat(lnId.prefix()).isEqualTo("Prefix"); + } + + @Test + void from_TLNode_LN0_should_succeed() { + //Given + TLNode tlNode = new TLNode(); + tlNode.setLnInst(""); + tlNode.getLnClass().add("LLN0"); + tlNode.setPrefix(""); + // When + LnId lnId = LnId.from(tlNode); + // Then + assertThat(lnId).isSameAs(LnId.LN0_ID); + } + +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ln/LnKeyTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ln/LnKeyTest.java deleted file mode 100644 index 4501f79d4..000000000 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ln/LnKeyTest.java +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: 2024 RTE FRANCE -// -// SPDX-License-Identifier: Apache-2.0 - - -package org.lfenergy.compas.sct.commons.scl.ln; - -import org.apache.commons.lang3.StringUtils; -import org.junit.jupiter.api.Test; -import org.lfenergy.compas.scl2007b4.model.LN0; -import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; -import org.lfenergy.compas.scl2007b4.model.TLN; -import org.lfenergy.compas.scl2007b4.model.TSystemLNGroupEnum; - -import static org.assertj.core.api.Assertions.assertThat; - -class LnKeyTest { - - @Test - void test_LnKey_withLN() { - //Given - TLN ln = new TLN(); - ln.setLnType("LnTypeAny"); - ln.setInst("1"); - ln.getLnClass().add(TSystemLNGroupEnum.LGOS.value()); - // When - LnKey lnKey = new LnKey(ln); - // Then - assertThat(lnKey.getLnType()).isEqualTo("LnTypeAny"); - assertThat(lnKey.getLnClass()).isEqualTo("LGOS"); - assertThat(lnKey.getInst()).isEqualTo("1"); - assertThat(lnKey.getPrefix()).isEqualTo(StringUtils.EMPTY); - } - - @Test - void test_LnKey_withLN0() { - //Given - LN0 ln0 = new LN0(); - ln0.setLnType("LnType0"); - ln0.getLnClass().add(TLLN0Enum.LLN_0.value()); - // When - LnKey lnKey = new LnKey(ln0); - // Then - assertThat(lnKey.getLnType()).isEqualTo("LnType0"); - assertThat(lnKey.getLnClass()).isEqualTo("LLN0"); - assertThat(lnKey.getInst()).isEqualTo(""); - assertThat(lnKey.getPrefix()).isEqualTo(StringUtils.EMPTY); - } - -} \ No newline at end of file diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclHelper.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclHelper.java index 0d843c335..c3232434a 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclHelper.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/SclHelper.java @@ -21,6 +21,7 @@ import java.util.Optional; import java.util.stream.Stream; +import static org.apache.commons.lang3.StringUtils.trimToEmpty; import static org.assertj.core.api.Assertions.assertThat; import static org.lfenergy.compas.sct.commons.util.SclConstructorHelper.newConnectedAp; import static org.lfenergy.compas.sct.commons.util.Utils.lnClassEquals; @@ -99,8 +100,29 @@ public static LNAdapter findLn(SCL scl, String iedName, String ldInst, String ln ); } + public static TAnyLN findAnyLn(SCL scl, String iedName, String ldInst, String lnClass, String lnInst, String prefix) { + TIED ied = scl.getIED().stream().filter(tied -> tied.getName().equals(iedName)) + .findFirst().orElseThrow(() -> new AssertionFailedError("IED with name=%s not found".formatted(iedName))); + TLDevice tlDevice = getLDevices(ied) + .filter(tlDevice1 -> tlDevice1.getInst().equals(ldInst)) + .findFirst().orElseThrow(() -> new AssertionFailedError("LDevice with inst=%s not found".formatted(ldInst))); + if (lnClass.equals(TLLN0Enum.LLN_0.value()) && tlDevice.isSetLN0()) { + return tlDevice.getLN0(); + } + return tlDevice.getLN().stream() + .filter(tln -> Utils.lnClassEquals(tln.getLnClass(), lnClass) && trimToEmpty(tln.getInst()).equals(trimToEmpty(lnInst)) && trimToEmpty(tln.getPrefix()).equals(trimToEmpty(prefix))) + .findFirst() + .orElseThrow(() -> new AssertionFailedError("LN (lnClass=%s, lnInst=%s, lnPrefix=%s) not found".formatted(lnClass, lnInst, prefix))); + } + + public static Stream getLDevices(TIED tied) { + return tied.getAccessPoint().stream() + .filter(TAccessPoint::isSetServer) + .flatMap(tAccessPoint -> tAccessPoint.getServer().getLDevice().stream()); + } + public static IDataParentAdapter findDoiOrSdi(AbstractLNAdapter lnAdapter, String dataTypeRef) { - if (dataTypeRef.length() < 1) { + if (dataTypeRef.isEmpty()) { Assertions.fail("dataTypeRef must at least contain a DO, but got: " + dataTypeRef); } String[] names = dataTypeRef.split("\\."); @@ -112,15 +134,16 @@ public static IDataParentAdapter findDoiOrSdi(AbstractLNAdapter lnAdapter, St } public static Optional findDai(SCL scl, String iedName, String ldInst, String doiName, String daiName) { - return scl.getIED().stream().filter(tied -> tied.getName().equals(iedName)) - .flatMap(tied -> tied.getAccessPoint().stream()) - .flatMap(tAccessPoint -> tAccessPoint.getServer().getLDevice().stream()) - .filter(tlDevice -> tlDevice.getInst().equals(ldInst)) - .flatMap(tlDevice -> tlDevice.getLN0().getDOI().stream()) + return findDai(scl, iedName, ldInst, "LLN0", "", "", doiName, daiName); + } + + public static Optional findDai(SCL scl, String iedName, String ldInst, String lnClass, String lnInst, String lnPrefix, String doiName, String daiName) { + return findAnyLn(scl, iedName, ldInst, lnClass, lnInst, lnPrefix) + .getDOI().stream() .filter(tdoi -> tdoi.getName().equals(doiName)) - .flatMap(tdoi -> tdoi.getSDIOrDAI().stream().map(tUnNaming -> (TDAI)tUnNaming)) + .flatMap(tdoi -> tdoi.getSDIOrDAI().stream().map(tUnNaming -> (TDAI) tUnNaming)) .filter(tdai -> tdai.getName().equals(daiName)) - .findFirst(); + .findFirst(); } public static AbstractDAIAdapter findDai(AbstractLNAdapter lnAdapter, String dataTypeRef) { @@ -143,16 +166,7 @@ public static String getValue(TDAI tdai) { } else if (tdai.getVal().size() > 1) { Assertions.fail("Expecting a single value for for DAI " + tdai.getName()); } - return tdai.getVal().get(0).getValue(); - } - - - public static LDeviceAdapter findLDeviceByLdName(SCL scl, String ldName) { - return new SclRootAdapter(scl).streamIEDAdapters() - .flatMap(IEDAdapter::streamLDeviceAdapters) - .filter(lDeviceAdapter -> ldName.equals(lDeviceAdapter.getLdName())) - .findFirst() - .orElseThrow(() -> new AssertionFailedError("LDevice with ldName=%s not found in SCD".formatted(ldName))); + return tdai.getVal().getFirst().getValue(); } public static DataSetAdapter findDataSet(SCL scl, String iedName, String ldInst, String dataSetName) { @@ -215,7 +229,7 @@ public static Stream streamAllExtRef(SCL scl) { } public static String getDaiValue(AbstractLNAdapter ln, String doiName, String daiName) { - return ln.getDOIAdapterByName(doiName).getDataAdapterByName(daiName).getCurrentElem().getVal().get(0).getValue(); + return ln.getDOIAdapterByName(doiName).getDataAdapterByName(daiName).getCurrentElem().getVal().getFirst().getValue(); } public static Stream streamAllConnectedApGseP(SCL scd, String pType) {