From 1a4911cda76596c790bc297c483e2ca7fa3b3d66 Mon Sep 17 00:00:00 2001 From: massifben <105049157+massifben@users.noreply.github.com> Date: Tue, 21 Jan 2025 18:41:20 +0100 Subject: [PATCH] feat(#459): Change LnService.getDaiModStVal Signed-off-by: massifben <105049157+massifben@users.noreply.github.com> --- .../compas/sct/commons/LdeviceService.java | 7 +- .../compas/sct/commons/LnService.java | 60 +++++++------- .../compas/sct/commons/dto/LNodeDTO.java | 21 +++-- .../compas/sct/commons/scl/ln/LnId.java | 81 +++++++++++++++++++ .../compas/sct/commons/scl/ln/LnKey.java | 37 --------- .../compas/sct/commons/LnServiceTest.java | 4 +- .../compas/sct/commons/scl/ln/LnIdTest.java | 69 ++++++++++++++++ .../compas/sct/commons/scl/ln/LnKeyTest.java | 50 ------------ .../sct/commons/testhelpers/SclHelper.java | 52 +++++++----- 9 files changed, 231 insertions(+), 150 deletions(-) create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ln/LnId.java delete mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ln/LnKey.java create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ln/LnIdTest.java delete mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ln/LnKeyTest.java 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..f36a51148 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,10 @@ package org.lfenergy.compas.sct.commons; -import org.lfenergy.compas.scl2007b4.model.*; +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; @@ -41,6 +44,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..50d55c585 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; @@ -60,33 +59,37 @@ 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) { + public Optional getDaiModStValValue(TAnyLN tAnyLN) { + return getDaiModStVal(tAnyLN) + .stream() + .flatMap(tdai -> tdai.getVal().stream()) + .map(TVal::getValue) + .findFirst() + .map(ActiveStatus::fromValue); + } + + public Optional getDaiModStVal(TAnyLN tAnyLN) { return tAnyLN .getDOI() .stream() .filter(tdoi -> MOD_DO_NAME.equals(tdoi.getName())) - .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); + .flatMap(tdoi -> tdoi.getSDIOrDAI().stream()) + .filter(TDAI.class::isInstance) + .map(TDAI.class::cast) + .filter(tdai -> STVAL_DA_NAME.equals(tdai.getName())) + .findFirst(); } + 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 +102,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 +119,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 +141,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 +201,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 +229,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 +250,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 +297,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/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/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) {