From 2ebc36efc3c92505e5188494c3aa1dff05278cbe Mon Sep 17 00:00:00 2001 From: Samir Romdhani Date: Thu, 8 Sep 2022 17:59:03 +0200 Subject: [PATCH] [68][164] Activation used LDevice and Deactivation unused LDevice Signed-off-by: Aliou DIAITE Signed-off-by: Samir Romdhani --- .../sct/commons/dto/ResumedDataTemplate.java | 7 + .../compas/sct/commons/dto/SclReport.java | 40 +++ .../sct/commons/scl/LDeviceActivation.java | 102 ++++++++ .../sct/commons/scl/SclElementAdapter.java | 14 +- .../sct/commons/scl/SclRootAdapter.java | 15 ++ .../compas/sct/commons/scl/SclService.java | 23 ++ .../sct/commons/scl/SubstationService.java | 45 ++-- .../commons/scl/com/CommunicationAdapter.java | 6 + .../commons/scl/com/ConnectedAPAdapter.java | 9 +- .../commons/scl/com/SubNetworkAdapter.java | 7 + .../compas/sct/commons/scl/dtt/DAAdapter.java | 8 + .../sct/commons/scl/dtt/DATypeAdapter.java | 13 + .../compas/sct/commons/scl/dtt/DOAdapter.java | 8 + .../sct/commons/scl/dtt/DOTypeAdapter.java | 8 + .../scl/dtt/DataTypeTemplateAdapter.java | 7 +- .../sct/commons/scl/dtt/EnumTypeAdapter.java | 7 + .../sct/commons/scl/dtt/LNodeTypeAdapter.java | 8 + .../sct/commons/scl/header/HeaderAdapter.java | 9 + .../commons/scl/ied/AbstractLNAdapter.java | 2 + .../sct/commons/scl/ied/DOIAdapter.java | 13 + .../sct/commons/scl/ied/IEDAdapter.java | 6 + .../sct/commons/scl/ied/LDeviceAdapter.java | 6 + .../sct/commons/scl/ied/LN0Adapter.java | 147 ++++++++++- .../compas/sct/commons/scl/ied/LNAdapter.java | 22 ++ .../sct/commons/scl/ied/RootSDIAdapter.java | 14 + .../sct/commons/scl/ied/SDIAdapter.java | 12 + .../sct/commons/scl/sstation/BayAdapter.java | 1 + .../compas/sct/commons/util/STValEnum.java | 21 ++ .../commons/scl/LDeviceActivationTest.java | 17 ++ .../sct/commons/scl/SclServiceTest.java | 247 ++++++++++++++++++ .../commons/scl/SubstationServiceTest.java | 18 ++ .../sct/commons/scl/ied/LN0AdapterTest.java | 48 ++++ .../issue68_Test1_LD_STATUS_INACTIVE.scd | 224 ++++++++++++++++ .../issue68_Test2_LD_STATUS_INACTIVE.scd | 222 ++++++++++++++++ .../issue68_Test_KO_MissingBeh.scd | 114 ++++++++ .../issue68_Test_KO_MissingLDevicePrivate.scd | 112 ++++++++ ...Test_KO_MissingLDevicePrivateAttribute.scd | 115 ++++++++ .../issue68_Test_KO_MissingMod.scd | 114 ++++++++ .../issue68_Test_LD_STATUS_ACTIVE.scd | 219 ++++++++++++++++ .../issue68_Test_LD_STATUS_UNTESTED.scd | 219 ++++++++++++++++ .../issue68_Test_Template.scd | 223 ++++++++++++++++ 41 files changed, 2434 insertions(+), 38 deletions(-) create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SclReport.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/LDeviceActivation.java create mode 100644 sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/STValEnum.java create mode 100644 sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/LDeviceActivationTest.java create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test1_LD_STATUS_INACTIVE.scd create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test2_LD_STATUS_INACTIVE.scd create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingBeh.scd create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivate.scd create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivateAttribute.scd create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingMod.scd create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_LD_STATUS_ACTIVE.scd create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_LD_STATUS_UNTESTED.scd create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_Template.scd 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 fe50c79c5..dd702a8c9 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 @@ -322,4 +322,11 @@ public void setValImport(boolean valImport) { public boolean isValImport(){ return daName.isValImport(); } + + public ResumedDataTemplate setNewVal(String daiValue) { + TVal newDaiVal = new TVal(); + newDaiVal.setValue(daiValue); + this.setDaiValues(List.of(newDaiVal)); + return this; + } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SclReport.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SclReport.java new file mode 100644 index 000000000..2a9e42679 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SclReport.java @@ -0,0 +1,40 @@ +/* + * // SPDX-FileCopyrightText: 2022 RTE FRANCE + * // + * // SPDX-License-Identifier: Apache-2.0 + */ + +package org.lfenergy.compas.sct.commons.dto; + +import lombok.*; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; + +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Setter +@Getter +@Builder +public class SclReport { + + private SclRootAdapter scdFile; + + private List errorDescriptionList = new ArrayList<>(); + + public boolean isSuccess() { + return errorDescriptionList.isEmpty(); + } + + @Getter + @Setter + @AllArgsConstructor + @ToString + @EqualsAndHashCode + @Builder + public static class ErrorDescription{ + private String xpath; + private String message; + } +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/LDeviceActivation.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/LDeviceActivation.java new file mode 100644 index 000000000..9525fe19d --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/LDeviceActivation.java @@ -0,0 +1,102 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + + +package org.lfenergy.compas.sct.commons.scl; + +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.tuple.Pair; +import org.lfenergy.compas.scl2007b4.model.TCompasLDeviceStatus; +import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; +import org.lfenergy.compas.sct.commons.util.STValEnum; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +@Getter +@Setter +public class LDeviceActivation { + + private final List> iedNameLdInstList; + + private TCompasLDeviceStatus compasLDeviceStatus; + private boolean isUpdatable; + private ResumedDataTemplate resumedDataTemplate; + private List errorMessages = new ArrayList<>(); + + public LDeviceActivation(List> iedNameLdInstList) { + this.iedNameLdInstList = iedNameLdInstList; + } + + public void checkLDeviceActivationStatus(String iedName, String ldInst, TCompasLDeviceStatus compasLDeviceStatus, Set enumValues) { + if (!enumValues.contains(STValEnum.ON.value) && !enumValues.contains(STValEnum.OFF.value)) { + errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'.", + iedName, ldInst)); + } + if (!enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) { + if (isAuthorized(iedName, ldInst)) { + errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s cannot be set to 'on' but has been selected into SSD: this case should not occur.", iedName, ldInst)); + } else { + isUpdatable = true; + resumedDataTemplate.setNewVal(STValEnum.OFF.value); + } + } + if(compasLDeviceStatus.equals(TCompasLDeviceStatus.ACTIVE) || + compasLDeviceStatus.equals(TCompasLDeviceStatus.UNTESTED)){ + isAuthorizedToActivateLDevice(iedName, ldInst, enumValues); + } + if(compasLDeviceStatus.equals(TCompasLDeviceStatus.INACTIVE)){ + isAuthorizedToDeactivateLDevice(iedName, ldInst, enumValues); + } + } + + private void isAuthorizedToActivateLDevice(String iedName, String ldInst, Set enumValues) { + if (!enumValues.contains(STValEnum.OFF.value) && enumValues.contains(STValEnum.ON.value)) { + if (isAuthorized(iedName, ldInst)) { + isUpdatable = true; + resumedDataTemplate.setNewVal(STValEnum.ON.value); + } else { + errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s cannot be set to 'off' but has not been selected into SSD: this case should not occur.", iedName, ldInst)); + } + } + if (enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) { + isUpdatable = true; + if (isAuthorized(iedName, ldInst)) { + resumedDataTemplate.setNewVal(STValEnum.ON.value); + } else { + resumedDataTemplate.setNewVal(STValEnum.OFF.value); + } + } + + } + + private void isAuthorizedToDeactivateLDevice(String iedName, String ldInst, Set enumValues) { + if (!enumValues.contains(STValEnum.OFF.value) && enumValues.contains(STValEnum.ON.value)) { + if (isAuthorized(iedName, ldInst)) { + errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s is not qualified into STD but has been selected into SSD: this case should not occur.", + iedName, ldInst)); + } else { + errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s cannot be set to 'off' but has not been selected into SSD: this case should not occur.", + iedName, ldInst)); + } + } + if (enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) { + if (isAuthorized(iedName, ldInst)) { + errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s is not qualified into STD but has been selected into SSD: this case should not occur.", + iedName, ldInst)); + } else { + isUpdatable = true; + resumedDataTemplate.setNewVal(STValEnum.OFF.value); + } + } + } + + private boolean isAuthorized(String iedName, String ldInst){ + return iedNameLdInstList.contains(Pair.of(iedName, ldInst)); + } + + +} 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 8d4b36f2b..1939dc07a 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 @@ -67,6 +67,12 @@ protected boolean amRootElement(){ return parentAdapter == null; } + /** + * Returns XPath path to current element + * @return message as undefined + */ + protected abstract String elementXPath(); + protected void customInit() { // do nothing } @@ -109,12 +115,4 @@ public String getXPath(){ return parentXpath + "/" + elementXPath(); } - /** - * Returns XPath path to current element - * @return message as undefined - */ - 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 c7698a6ac..fc410cd51 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 @@ -18,6 +18,7 @@ import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -140,6 +141,19 @@ public SubstationAdapter getSubstationAdapter(String ssName) throws ScdException return new SubstationAdapter(this,ssName); } + /** + * TODO + * @return + * @throws ScdException + */ + public SubstationAdapter getSubstationAdapter() throws ScdException { + TSubstation tSubstation = currentElem.getSubstation() + .stream() + .findFirst() + .orElseThrow(() -> new ScdException("No Substation in SCL file")); + return new SubstationAdapter(this, tSubstation); + } + /** * Add Header to SCL root node * @param hId SCL Header ID @@ -275,4 +289,5 @@ public IEDAdapter checkObjRef(String val) throws ScdException { } throw new ScdException("Invalid ObjRef: " + val); } + } 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 21119cd86..d643337ef 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 @@ -680,4 +680,27 @@ public static void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final S .forEach(LNAdapter::removeAllControlBlocksAndDatasets); } + /** + * Activate used LDevice and Deactivate unused LDevice in {@link TLNode TLNode } + * @param scd SCL file for which LDevice should be activated or deactivated + * @return SclReport Object that contain SCL file and set of errors + */ + public static SclReport updateLDeviceStatus(SCL scd) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + final List> iedNameLdInstList = SubstationService.getLDevicesFromLNode(sclRootAdapter, true); + LDeviceActivation lDeviceActivate = new LDeviceActivation(iedNameLdInstList); + Optional> errors = sclRootAdapter.getIEDAdapters().stream() + .map(IEDAdapter::getLDeviceAdapters) + .flatMap(Collection::stream) + .map(LDeviceAdapter::getLN0Adapter) + .map(ln0Adapter -> ln0Adapter.checkAndUpdateLDevice(lDeviceActivate)) + .reduce((partialSclReportErrors, sclReportErrors) -> { + partialSclReportErrors.addAll(sclReportErrors); + return partialSclReportErrors; + }); + SclReport sclReport = new SclReport(); + errors.ifPresent(errorDescriptions -> sclReport.getErrorDescriptionList().addAll(errorDescriptions)); + sclReport.setScdFile(sclRootAdapter); + return sclReport; + } } 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 index dec6e4b22..6c6cc3c89 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SubstationService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/SubstationService.java @@ -6,32 +6,17 @@ 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.apache.commons.lang3.tuple.Pair; +import org.lfenergy.compas.scl2007b4.model.*; 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.SubstationAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; -/** - * A representation of the {@link SubstationService SubstationService}. - *

- * The following features are supported: - *

- *
    - *
  • {@link SubstationService#addSubstation(SCL, SCL) Adds the Substation object from given SCL object}
  • - *
  • {@link SubstationService#updateVoltageLevel(SubstationAdapter, TVoltageLevel) Adds the TVoltageLevel element under TSubstation reference object}
  • - *
  • {@link SubstationService#updateBay(VoltageLevelAdapter, TBay) Adds the TBay element under TVoltageLevel reference object}
  • - *
- * @see org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter - * @see org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter - * @see org.lfenergy.compas.sct.commons.scl.sstation.BayAdapter - * @see org.lfenergy.compas.sct.commons.scl.sstation.FunctionAdapter - * @see org.lfenergy.compas.sct.commons.scl.sstation.LNodeAdapter - * @see org.lfenergy.compas.sct.commons.scl.PrivateService - */ @Slf4j public final class SubstationService { @@ -112,4 +97,22 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte } } + /** + * + * @param sclRootAdapter + * @return + */ + public static List> getLDevicesFromLNode(SclRootAdapter sclRootAdapter, boolean isLN0) { + if (!sclRootAdapter.getCurrentElem().isSetSubstation()) { + return new ArrayList<>(); + } + return sclRootAdapter.getSubstationAdapter() + .streamVoltageLevelAdapters() + .flatMap(VoltageLevelAdapter::streamBayAdapters) + .flatMap(BayAdapter::streamFunctionAdapters) + .flatMap(functionAdapter -> functionAdapter.getCurrentElem().getLNode().stream()) + .filter(tlNode -> !isLN0 || tlNode.getLnClass().contains(TLLN0Enum.LLN_0.value())) + .map(tlNode -> Pair.of(tlNode.getIedName(), tlNode.getLdInst())) + .collect(Collectors.toList()); + } } 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 333584ce1..a21cdec6a 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 @@ -11,6 +11,7 @@ import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.List; import java.util.Optional; @@ -58,6 +59,11 @@ public boolean amChildElementRef() { return currentElem == parentAdapter.getCurrentElem().getCommunication(); } + @Override + protected String elementXPath() { + return "Communication"; + } + /** * Add Subnetwork node in Communication one. * For that : 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 36ca4c3b0..d2bf8b62d 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,8 +6,8 @@ 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 org.lfenergy.compas.sct.commons.util.Utils; import java.util.Optional; @@ -45,6 +45,13 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getConnectedAP().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("ConnectedAP[apName=%s and iedName=%s]", + Utils.xpathAttributeFilter("apName", currentElem.isSetApName() ? currentElem.getApName() : null), + Utils.xpathAttributeFilter("iedName", currentElem.isSetIedName() ? currentElem.getApName() : null)); + } + /** * Returns the value of the iedName attribute. * @return the value of the iedName attribute. 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 5a6333eef..960ea6e49 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 @@ -9,6 +9,7 @@ import org.lfenergy.compas.scl2007b4.model.TSubNetwork; 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.List; import java.util.Objects; @@ -48,6 +49,12 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSubNetwork().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("SubNetwork[name=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + /** * Create a Connected Access Point for this subnetwork.
*

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 925eec136..a07d04571 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 @@ -8,6 +8,7 @@ import org.lfenergy.compas.scl2007b4.model.TDA; import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.util.Utils; /** * A representation of the model object {@link org.lfenergy.compas.scl2007b4.model.TDA DA}. @@ -57,6 +58,13 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSDOOrDA().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("DA[name=%s and type=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null), + Utils.xpathAttributeFilter("type", currentElem.isSetType() ? currentElem.getType() : null)); + } + /** * Updates DA Type Name * @param daTypeName DA Type Name to update 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 0402fa774..dab6d37a6 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 @@ -14,6 +14,7 @@ import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.ArrayList; import java.util.List; @@ -154,6 +155,12 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getDAType().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("DAType[id=%s]", + Utils.xpathAttributeFilter("id", currentElem.isSetId() ? currentElem.getId() : null)); + } + /** * Gets all BDAs from current DAType * @return list of linked BDA as BDAAdapter object @@ -390,5 +397,11 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getBDA().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("BDA[id=%s]", + Utils.xpathAttributeFilter("id", currentElem.isSetName() ? currentElem.getName() : null)); + } + } } 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 711a39f97..75fbb6445 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 @@ -6,6 +6,7 @@ import org.lfenergy.compas.scl2007b4.model.TDO; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.Optional; @@ -53,6 +54,13 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getDO().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("DO[name=%s and type=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null), + Utils.xpathAttributeFilter("type", currentElem.isSetType() ? currentElem.getType() : null)); + } + /** * Gets linked DataTypeTemplateAdapter as parent * @return DataTypeTemplateAdapter object 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 3f7fd8aa9..4871a7258 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 @@ -11,6 +11,7 @@ import org.lfenergy.compas.sct.commons.dto.DoTypeName; import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.*; import java.util.stream.Collectors; @@ -183,6 +184,13 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getDOType().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("DOType[id=%s]", + Utils.xpathAttributeFilter("id", currentElem.isSetId() ? currentElem.getId() : null)); + } + + /** * Checks if current DOType contains DA * @param da DA name 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 488781267..587f1062c 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 @@ -13,7 +13,6 @@ import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; -import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; import java.util.*; import java.util.stream.Collectors; @@ -90,6 +89,12 @@ protected boolean amChildElementRef() { return currentElem == parentAdapter.getCurrentElem().getDataTypeTemplates(); } + @Override + protected String elementXPath() { + return "DataTypeTemplates"; + } + + /** * Gets LNodeType from DataTypeTemplate by ID in LNodeTypeAdapter * @param id LNodeType 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 d184ab835..d946ca69d 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,6 +7,7 @@ import org.lfenergy.compas.scl2007b4.model.TEnumType; import org.lfenergy.compas.scl2007b4.model.TEnumVal; +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.List; import java.util.Objects; @@ -53,6 +54,12 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getEnumType().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("EnumType[id=%s]", + Utils.xpathAttributeFilter("id", currentElem.isSetId() ? currentElem.getId() : null)); + } + /** * Compares current EnumType and given EnumType * @param tEnumType EnumType to compare with 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 6d25c83e3..92d2878c8 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 @@ -15,6 +15,7 @@ import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; 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.ArrayList; import java.util.List; @@ -71,6 +72,13 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getLNodeType().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("LNodeType[id=%s and lnClass=%s]", + Utils.xpathAttributeFilter("id", currentElem.isSetId() ? currentElem.getId() : null), + Utils.xpathAttributeFilter("lnClass", currentElem.isSetLnClass() ? currentElem.getLnClass() : null)); + } + /** * Compares current LNodeType and given LNodeType * @param tlNodeType LNodeType to compare with 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 3b1bee252..83889eaea 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 @@ -9,6 +9,7 @@ import org.lfenergy.compas.scl2007b4.model.TPrivate; 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.ArrayList; import java.util.Date; @@ -55,6 +56,14 @@ protected boolean amChildElementRef() { return currentElem == parentAdapter.getCurrentElem().getHeader(); } + @Override + protected String elementXPath() { + return String.format("Header[id=%s and version=%s and revision=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetId() ? currentElem.getId() : null), + Utils.xpathAttributeFilter("version", currentElem.isSetVersion() ? currentElem.getVersion() : null), + Utils.xpathAttributeFilter("revision", currentElem.isSetRevision() ? currentElem.getRevision() : null)); + } + /** * @param who input * @param what input 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 0c1b52255..00f0be788 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 @@ -90,6 +90,8 @@ public static LNAdapterBuilder builder(){ public abstract String getLNInst(); public abstract String getPrefix(); + public abstract Set getEnumValue(ResumedDataTemplate rdt); + /** * Add given ControlBlock to LNode * @param controlBlock ControlBlock to add 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 54414d7b9..35a546c09 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 @@ -10,6 +10,7 @@ import org.lfenergy.compas.scl2007b4.model.TSDI; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; /** @@ -56,6 +57,12 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getDOI().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("DOI[name=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + /** * Gets SDI by name from current DOI * @param sName name of SDI to get @@ -161,5 +168,11 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSDIOrDAI().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("DAI[name=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + } } 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 6d3c5455a..fd84454af 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 @@ -15,6 +15,7 @@ import org.lfenergy.compas.sct.commons.scl.ObjectReference; 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.*; import java.util.stream.Collectors; @@ -99,6 +100,11 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getIED().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("IED[%s]", Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + /** * Sets IED name in current IED * @param iedName new name to set 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 c2f6fa0ea..a037accc3 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 @@ -14,6 +14,7 @@ import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; import java.util.*; import java.util.stream.Collectors; @@ -75,6 +76,11 @@ protected boolean amChildElementRef() { .anyMatch(tlDevice -> currentElem.getInst().equals(tlDevice.getInst())); } + @Override + protected String elementXPath() { + return String.format("LDevice[%s]", Utils.xpathAttributeFilter("inst", currentElem.isSetInst() ? currentElem.getInst() : null)); + } + /** * Updates LDevice name by combining IED name and LDevice ldInst value * @throws ScdException throws when renaming LDevice and new name has more than 33 caracteres 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 a443250fc..79808c8a4 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 @@ -5,15 +5,16 @@ package org.lfenergy.compas.sct.commons.scl.ied; -import org.lfenergy.compas.scl2007b4.model.LN0; -import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; -import org.lfenergy.compas.scl2007b4.model.TServiceType; -import org.lfenergy.compas.sct.commons.dto.ExtRefInfo; -import org.lfenergy.compas.sct.commons.dto.ExtRefSignalInfo; -import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; +import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.dto.*; +import org.lfenergy.compas.sct.commons.scl.LDeviceActivation; import org.lfenergy.compas.sct.commons.scl.ObjectReference; +import org.lfenergy.compas.sct.commons.scl.PrivateService; +import org.lfenergy.compas.sct.commons.scl.dtt.EnumTypeAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; -import java.util.List; +import java.util.*; +import java.util.stream.Collectors; /** * A representation of the model object @@ -83,6 +84,13 @@ protected boolean amChildElementRef() { return currentElem == parentAdapter.getCurrentElem().getLN0(); } + @Override + protected String elementXPath() { + return String.format("LN[lnClass=LLN0 and %s and %s]", + Utils.xpathAttributeFilter("inst", currentElem.isSetInst() ? currentElem.getInst() : null), + Utils.xpathAttributeFilter("lnType", currentElem.isSetLnType() ? currentElem.getLnType() : null)); + } + /** * Gets current LN0 class type * @return LN0.class @@ -118,6 +126,26 @@ public String getPrefix() { return ""; } + /** + * Returns sets of enum value for given ResumedDataTemplate object + * @param filter ResumedDataTemplate object + * @return Enum value list + */ + @Override + public Set getEnumValue(ResumedDataTemplate filter) { + List daiList = getDAI(filter, false); + Optional enumTypeAdapter = parentAdapter + .getParentAdapter().getParentAdapter().getDataTypeTemplateAdapter() + .getEnumTypeAdapterById(daiList.get(0).getDaName().getType()); + + if(enumTypeAdapter.isEmpty()){ + return new HashSet<>(); + } + return enumTypeAdapter.get().getCurrentElem().getEnumVal() + .stream().map(TEnumVal::getValue) + .collect(Collectors.toSet()); + } + /** Checks if given attibrute corresponds to DataSet or ReportControl or SMVControl or GSEControl in current LN0 * @param dataAttribute attribute to check * @return Boolean value of check result @@ -138,4 +166,109 @@ public void removeAllControlBlocksAndDatasets() { currentElem.unsetGSEControl(); currentElem.unsetSampledValueControl(); } + + /** + * Construct ResumedDataTemplate object with DO and DA attributes + * @param doName The value of the name attribute of DO object + * @param daTypeName DaTypeName object + * @return ResumedDataTemplate + */ + private ResumedDataTemplate getResumedDataTemplate(String doName, DaTypeName daTypeName) { + ResumedDataTemplate filter = new ResumedDataTemplate(); + filter.setLnClass(getLNClass()); + filter.setLnInst(getLNInst()); + filter.setPrefix(getPrefix()); + filter.setLnType(getLnType()); + filter.setDoName(new DoTypeName(doName)); + filter.setDaName(daTypeName); + return filter; + } + + /** + * Verify and update LDevice status in parent Node + * @param lDeviceActivation LDeviceActivation wich + * @return Set of Errors + */ + public List checkAndUpdateLDevice(LDeviceActivation lDeviceActivation) { + List errors = new ArrayList<>(); + lDeviceActivation.getErrorMessages().clear(); + final String iedName = getParentAdapter().getParentAdapter().getName(); + final String ldInst = getParentAdapter().getInst(); + final String behaviourDO = "Beh"; + final String targetDO = "Mod"; + final String targetDA = "stVal"; + DaTypeName daTypeName = new DaTypeName(); + daTypeName.setName(targetDA); + daTypeName.setBType(TPredefinedBasicTypeEnum.ENUM); + daTypeName.setFc(TFCEnum.ST); + ResumedDataTemplate daiBehFilter = getResumedDataTemplate(behaviourDO, daTypeName); + List daiBehList = getDAI(daiBehFilter, false); + if (daiBehList.isEmpty()) { + buildErrorMessage(errors, getXPath(), + "The IED@%s/LDevice@%s doesn't have a DO @name='Beh' OR its associated DA@fc='ST' AND DA@name='stVal'", + iedName, ldInst); + return errors; + } + Set enumValues = getEnumValue(daiBehList.get(0)); + List compasLDevicePrivateList = PrivateService.getCompasPrivates(getParentAdapter().getCurrentElem(), TCompasLDevice.class); + if (compasLDevicePrivateList.isEmpty()) { + buildErrorMessage(errors, getXPath(), + "The IED@%s/LDevice@%s doesn't have a Private compas:LDevice.", + iedName, ldInst); + return errors; + } + if (!compasLDevicePrivateList.get(0).isSetLDeviceStatus()) { + buildErrorMessage(errors, getXPath(), + "The IED@%s/LDevice@%s Private compas:LDevice doesn't have the attribute 'LDeviceStatus'", + iedName, ldInst); + return errors; + } + TCompasLDeviceStatus compasLDeviceStatus = compasLDevicePrivateList.get(0).getLDeviceStatus(); + DaTypeName modTypeName = new DaTypeName(); + daTypeName.setName(targetDA); + ResumedDataTemplate daiModFilter = getResumedDataTemplate(targetDO, modTypeName); + List daiModList = getDAI(daiModFilter, false); + if (daiModList.isEmpty()) { + buildErrorMessage(errors, getXPath(), + "The IED@%s/LDevice@%s doesn't have a DO @name='Mod'", + iedName, ldInst); + return errors; + } + ResumedDataTemplate daiMod = daiModList.get(0); + String initialValue = daiMod.getDaName().getDaiValues().isEmpty() ? "" : daiMod.getDaName().getDaiValues().values().toArray()[0].toString(); + lDeviceActivation.setResumedDataTemplate(daiMod); + lDeviceActivation.checkLDeviceActivationStatus(iedName, ldInst, compasLDeviceStatus, enumValues); + if(Boolean.TRUE.equals(lDeviceActivation.isUpdatable())){ + if(!initialValue.equals(lDeviceActivation.getResumedDataTemplate().getDaName().getDaiValues().values().toArray()[0])) { + updateDAI(lDeviceActivation.getResumedDataTemplate()); + } + }else { + List errorDescriptionList = lDeviceActivation.getErrorMessages() + .stream() + .map(errorMessage -> SclReport.ErrorDescription.builder() + .xpath(getXPath()) + .message(errorMessage) + .build()) + .collect(Collectors.toList()); + errors.addAll(errorDescriptionList); + } + return errors; + } + + /** + * Update ErrorDescription list of SclReport object with given xpath and message + * @param errors input parameter + * @param xpath input parameter + * @param message input parameter + * @param iedName input parameter + * @param ldInst input parameter + */ + private void buildErrorMessage(List errors, String xpath, String message, String iedName, String ldInst) { + String msg = String.format(message, iedName, ldInst); + errors.add(SclReport.ErrorDescription.builder() + .message(msg) + .xpath(xpath) + .build()); + } + } 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 90bc1b5e5..fd0b70983 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 @@ -10,8 +10,11 @@ import org.lfenergy.compas.sct.commons.dto.ExtRefSignalInfo; import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; import org.lfenergy.compas.sct.commons.scl.ObjectReference; +import org.lfenergy.compas.sct.commons.util.Utils; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** @@ -113,6 +116,17 @@ public String getPrefix() { return currentElem.getPrefix(); } + + /** + * TODO + * @param rdt + * @return + */ + @Override + public Set getEnumValue(ResumedDataTemplate rdt) { + return new HashSet<>(); + } + /** * Check if node is child of the reference node * @return link parent child existence @@ -123,4 +137,12 @@ protected boolean amChildElementRef() { // as there's no equals method in TLN return parentAdapter.getCurrentElem().getLN().contains(currentElem); } + + @Override + protected String elementXPath() { + return String.format("LN[%s and %s and %s]", + Utils.xpathAttributeFilter("lnClass", currentElem.isSetLnClass() ? currentElem.getLnClass() : null), + Utils.xpathAttributeFilter("inst", currentElem.isSetInst() ? currentElem.getInst() : null), + Utils.xpathAttributeFilter("lnType", currentElem.isSetLnType() ? currentElem.getLnType() : null)); + } } 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 d447610ca..3e7282e4b 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 @@ -8,6 +8,7 @@ import org.lfenergy.compas.scl2007b4.model.TSDI; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; /** @@ -52,6 +53,13 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSDIOrDAI().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("SDI[name=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + + /** * Gets in current root SDI specific SDI by its name * @param name name of SDI to get @@ -152,5 +160,11 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSDIOrDAI().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("DAI[name=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + } } 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 46399ddf3..1194680a1 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 @@ -8,6 +8,7 @@ import org.lfenergy.compas.scl2007b4.model.TSDI; 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; @@ -57,6 +58,12 @@ protected boolean amChildElementRef() { return SDIAdapter.class.cast(parentAdapter).getCurrentElem().getSDIOrDAI().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("SDI[name=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } + /** * Gets in current SDI specific SDI by its name * @param sName name of SDI to get @@ -162,5 +169,10 @@ protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getSDIOrDAI().contains(currentElem); } + @Override + protected String elementXPath() { + return String.format("DAI[name=%s]", + Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null)); + } } } 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 a8ad47551..cb805f7f5 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 @@ -97,4 +97,5 @@ public Stream streamFunctionAdapters(){ } return currentElem.getFunction().stream().map(tFunction -> new FunctionAdapter(this, tFunction)); } + } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/STValEnum.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/STValEnum.java new file mode 100644 index 000000000..3b1559172 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/STValEnum.java @@ -0,0 +1,21 @@ +/* + * // SPDX-FileCopyrightText: 2022 RTE FRANCE + * // + * // SPDX-License-Identifier: Apache-2.0 + */ + +package org.lfenergy.compas.sct.commons.util; + +/** + * A representation of a specific object TDAI name that have attribute name STVal. + * + * @see org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum + */ +public enum STValEnum { + ON("on"), + OFF("off"); + public final String value; + STValEnum(String value) { + this.value = value; + } +} \ No newline at end of file diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/LDeviceActivationTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/LDeviceActivationTest.java new file mode 100644 index 000000000..6a661a72a --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/LDeviceActivationTest.java @@ -0,0 +1,17 @@ +package org.lfenergy.compas.sct.commons.scl; + +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.TCompasLDeviceStatus; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +import static org.junit.jupiter.api.Assertions.*; + +class LDeviceActivationTest { + + @Test + void checkLDeviceActivationStatus() { + } + +} \ 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 571891ae9..a2ffd1884 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 @@ -5,7 +5,13 @@ package org.lfenergy.compas.sct.commons.scl; import org.apache.commons.lang3.StringUtils; +import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestFactory; +import org.junit.jupiter.api.function.Executable; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; @@ -14,12 +20,15 @@ import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.DynamicTest.dynamicTest; 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.testhelpers.marshaller.SclTestMarshaller.createWrapper; import static org.lfenergy.compas.sct.commons.util.PrivateEnum.COMPAS_SCL_FILE_TYPE; class SclServiceTest { @@ -701,4 +710,242 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_srcXXX_attributes_o assertIsMarshallable(scl); } + + @Test + void updateLDeviceStatus_shouldReturnReportWithError_WhenMissingDOBeh() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_KO_MissingBeh.scd"); + String before = createWrapper().marshall(scl); + // When + SclReport sclReport = SclService.updateLDeviceStatus(scl); + String after = createWrapper().marshall(sclReport.getScdFile().getCurrentElem()); + // Then + assertFalse(sclReport.isSuccess()); + assertThat(sclReport.getErrorDescriptionList()) + .hasSize(1) + .extracting(SclReport.ErrorDescription::getMessage) + .containsExactly( + "The IED@IedName1/LDevice@LDSUIED doesn't have a DO @name='Beh' OR its associated DA@fc='ST' AND DA@name='stVal'"); + assertEquals(before, after); + } + @Test + void updateLDeviceStatus_shouldReturnReportWithError_WhenMissingLDevicePrivate() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivate.scd"); + assertTrue(getLDeviceStatusValue(scl, "IedName1", "LDSUIED").isPresent()); + assertEquals("off", getLDeviceStatusValue(scl, "IedName1", "LDSUIED").get().getValue()); + // When + SclReport sclReport = SclService.updateLDeviceStatus(scl); + // Then + assertFalse(sclReport.isSuccess()); + assertThat(sclReport.getErrorDescriptionList()) + .hasSize(1) + .containsExactly(SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType1\"]") + .message("The IED@IedName1/LDevice@LDSUIED doesn't have a Private compas:LDevice.") + .build()); + assertEquals("off", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); + } + + @Test + void updateLDeviceStatus_shouldReturnReportWithError_WhenMissingLDevicePrivateAttribute() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivateAttribute.scd"); + assertTrue(getLDeviceStatusValue(scl, "IedName1", "LDSUIED").isPresent()); + assertEquals("off", getLDeviceStatusValue(scl, "IedName1", "LDSUIED").get().getValue()); + // When + SclReport sclReport = SclService.updateLDeviceStatus(scl); + // Then + assertFalse(sclReport.isSuccess()); + assertThat(sclReport.getErrorDescriptionList()) + .hasSize(1) + .containsExactly(SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType1\"]") + .message("The IED@IedName1/LDevice@LDSUIED Private compas:LDevice doesn't have the attribute 'LDeviceStatus'") + .build()); + assertEquals("off", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); + } + + @Test + void updateLDeviceStatus_shouldReturnReportWithError_WhenMissingDOMod() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_KO_MissingMod.scd"); + assertTrue(getLDeviceStatusValue(scl, "IedName1", "LDSUIED").isPresent()); + assertEquals("off", getLDeviceStatusValue(scl, "IedName1", "LDSUIED").get().getValue()); + // When + SclReport sclReport = SclService.updateLDeviceStatus(scl); + // Then + assertFalse(sclReport.isSuccess()); + assertThat(sclReport.getErrorDescriptionList()) + .hasSize(1) + .containsExactly(SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType1\"]") + .message("The IED@IedName1/LDevice@LDSUIED doesn't have a DO @name='Mod'") + .build()); + assertEquals( "off",getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); + } + + @Test + void updateLDeviceStatus_shouldReturnReportWithError_WhenAllLDeviceActive() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_LD_STATUS_ACTIVE.scd"); + assertEquals("off", getLDeviceStatusValue(scl, "IedName1", "LDSUIED").get().getValue()); + assertEquals("on", getLDeviceStatusValue(scl, "IedName2", "LDSUIED").get().getValue()); + assertFalse(getLDeviceStatusValue(scl, "IedName3", "LDSUIED").isPresent()); + // When + SclReport sclReport = SclService.updateLDeviceStatus(scl); + // Then + assertFalse(sclReport.isSuccess()); + assertThat(sclReport.getErrorDescriptionList()) + .hasSize(3) + .contains(SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType1\"]") + .message("Unexpected error: The IED@IedName1/LDevice@LDSUIED cannot be set to 'off' but has not been selected into SSD: this case should not occur.") + .build(), + SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName2\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType2\"]") + .message("Unexpected error: The IED@IedName2/LDevice@LDSUIED cannot be set to 'on' but has been selected into SSD: this case should not occur.") + .build(), + SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName3\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType3\"]") + .message("Unexpected error: The IED@IedName3/LDevice@LDSUIED cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'.") + .build()); + assertEquals("off", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); + assertEquals("on", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName2", "LDSUIED").get().getValue()); + assertFalse(getLDeviceStatusValue(scl, "IedName3", "LDSUIED").isPresent()); + } + + + @Test + void updateLDeviceStatus_shouldReturnReportWithError_WhenAllLDeviceUntested() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_LD_STATUS_UNTESTED.scd"); + assertEquals("off", getLDeviceStatusValue(scl, "IedName1", "LDSUIED").get().getValue()); + assertEquals("on", getLDeviceStatusValue(scl, "IedName2", "LDSUIED").get().getValue()); + assertFalse(getLDeviceStatusValue(scl, "IedName3", "LDSUIED").isPresent()); + // When + SclReport sclReport = SclService.updateLDeviceStatus(scl); + // Then + assertFalse(sclReport.isSuccess()); + assertThat(sclReport.getErrorDescriptionList()) + .hasSize(3) + .contains(SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType1\"]") + .message("Unexpected error: The IED@IedName1/LDevice@LDSUIED cannot be set to 'off' but has not been selected into SSD: this case should not occur.") + .build(), + SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName2\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType2\"]") + .message("Unexpected error: The IED@IedName2/LDevice@LDSUIED cannot be set to 'on' but has been selected into SSD: this case should not occur.") + .build(), + SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName3\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType3\"]") + .message("Unexpected error: The IED@IedName3/LDevice@LDSUIED cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'.") + .build()); + assertEquals("off", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); + assertEquals("on", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName2", "LDSUIED").get().getValue()); + assertFalse(getLDeviceStatusValue(scl, "IedName3", "LDSUIED").isPresent()); + } + + @Test + void updateLDeviceStatus_shouldReturnReportWithError_WhenAllLDeviceInactive_Test1() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test1_LD_STATUS_INACTIVE.scd"); + assertEquals("off", getLDeviceStatusValue(scl, "IedName1", "LDSUIED").get().getValue()); + assertEquals("on", getLDeviceStatusValue(scl, "IedName2", "LDSUIED").get().getValue()); + assertFalse(getLDeviceStatusValue(scl, "IedName3", "LDSUIED").isPresent()); + // When + SclReport sclReport = SclService.updateLDeviceStatus(scl); + // Then + assertFalse(sclReport.isSuccess()); + assertThat(sclReport.getErrorDescriptionList()) + .hasSize(3) + .contains(SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType1\"]") + .message("Unexpected error: The IED@IedName1/LDevice@LDSUIED is not qualified into STD but has been selected into SSD: this case should not occur.") + .build(), + SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName2\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType2\"]") + .message("Unexpected error: The IED@IedName2/LDevice@LDSUIED cannot be set to 'on' but has been selected into SSD: this case should not occur.") + .build(), + SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName3\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType3\"]") + .message("Unexpected error: The IED@IedName3/LDevice@LDSUIED cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'.") + .build()); + assertEquals("off", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); + assertEquals("on", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName2", "LDSUIED").get().getValue()); + assertFalse(getLDeviceStatusValue(scl, "IedName3", "LDSUIED").isPresent()); + } + + @Test + void updateLDeviceStatus_shouldReturnReportWithError_WhenAllLDeviceInactive_Test2() throws Exception { + // Given + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test2_LD_STATUS_INACTIVE.scd"); + assertEquals("off", getLDeviceStatusValue(scl, "IedName1", "LDSUIED").get().getValue()); + assertEquals("on", getLDeviceStatusValue(scl, "IedName2", "LDSUIED").get().getValue()); + assertFalse(getLDeviceStatusValue(scl, "IedName3", "LDSUIED").isPresent()); + // When + SclReport sclReport = SclService.updateLDeviceStatus(scl); + // Then + assertFalse(sclReport.isSuccess()); + assertThat(sclReport.getErrorDescriptionList()) + .hasSize(2) + .contains(SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType1\"]") + .message("Unexpected error: The IED@IedName1/LDevice@LDSUIED cannot be set to 'off' but has not been selected into SSD: this case should not occur.") + .build(), + SclReport.ErrorDescription.builder() + .xpath("/SCL/IED[@name=\"IedName2\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=LLN0 and @inst=\"\" and @lnType=\"LNType2\"]") + .message("Unexpected error: The IED@IedName2/LDevice@LDSUIED is not qualified into STD but has been selected into SSD: this case should not occur.") + .build()); + assertEquals("off", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); + assertEquals("on", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName2", "LDSUIED").get().getValue()); + assertTrue(getLDeviceStatusValue(scl, "IedName3", "LDSUIED").isPresent()); + assertEquals("off", getLDeviceStatusValue(scl, "IedName3", "LDSUIED").get().getValue()); + } + + + @Test + void updateLDeviceStatus_shouldReturnUpdatedFile() throws Exception { + // Given + SCL givenScl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_Template.scd"); + assertTrue(getLDeviceStatusValue(givenScl, "IedName1", "LDSUIED").isPresent()); + assertEquals("off", getLDeviceStatusValue(givenScl, "IedName1", "LDSUIED").get().getValue()); + + assertTrue(getLDeviceStatusValue(givenScl, "IedName2", "LDSUIED").isPresent()); + assertEquals("on", getLDeviceStatusValue(givenScl, "IedName2", "LDSUIED").get().getValue()); + + assertFalse(getLDeviceStatusValue(givenScl, "IedName3", "LDSUIED").isPresent()); + + // When + SclReport sclReport = SclService.updateLDeviceStatus(givenScl); + // Then + assertTrue(sclReport.isSuccess()); + assertTrue(getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName1", "LDSUIED").isPresent()); + assertEquals("on", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); + + assertTrue(getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName2", "LDSUIED").isPresent()); + assertEquals("off", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName2", "LDSUIED").get().getValue()); + + assertTrue(getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName3", "LDSUIED").isPresent()); + assertEquals("off", getLDeviceStatusValue(sclReport.getScdFile().getCurrentElem(), "IedName3", "LDSUIED").get().getValue()); + } + + + private Optional getLDeviceStatusValue(SCL scl, String iedName, String ldInst){ + SclRootAdapter sclRootAdapter = new SclRootAdapter(scl); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); + Optional lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst); + LN0Adapter ln0Adapter = lDeviceAdapter.get().getLN0Adapter(); + Optional doiAdapter = ln0Adapter.getDOIAdapters().stream() + .filter(doiAdapter1 -> doiAdapter1.getCurrentElem().getName().equals("Mod")) + .findFirst(); + if(doiAdapter.isEmpty()) return Optional.empty(); + return doiAdapter.get().getCurrentElem().getSDIOrDAI().stream() + .filter(tUnNaming -> tUnNaming.getClass().equals(TDAI.class)) + .map(TDAI.class::cast) + .filter(tdai -> tdai.getName().equals("stVal")) + .map(tdai -> tdai.getVal().get(0)) + .findFirst(); + } + } 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 index 16d46ef35..b2e27c93d 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SubstationServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SubstationServiceTest.java @@ -4,12 +4,15 @@ package org.lfenergy.compas.sct.commons.scl; +import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.Test; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TSubstation; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import java.util.List; + import static org.junit.jupiter.api.Assertions.*; import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; @@ -77,4 +80,19 @@ void addSubstation_when_substations_names_differ_should_throw_exception() throws assertThrows(ScdException.class, () -> SubstationService.addSubstation(scd, ssd)); } + @Test + void getLDevicesFromLNode_test1_withoutLN0() throws Exception { + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/scd-with-substation-lnode.xml"); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scl); + List> iedNameLdInstList = SubstationService.getLDevicesFromLNode(sclRootAdapter, false); + assertEquals(2, iedNameLdInstList.size()); + } + + @Test + void getLDevicesFromLNode_test2_withLN0() throws Exception { + SCL scl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_Template.scd"); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scl); + List> iedNameLdInstList = SubstationService.getLDevicesFromLNode(sclRootAdapter, true); + assertEquals(1, iedNameLdInstList.size()); + } } 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 5b05181e3..ad16b5102 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 @@ -14,6 +14,7 @@ import org.mockito.Mockito; import java.util.List; +import java.util.Set; import static org.junit.jupiter.api.Assertions.*; @@ -325,4 +326,51 @@ void addPrivate() { lnAdapter.addPrivate(tPrivate); assertEquals(1, lnAdapter.getCurrentElem().getPrivate().size()); } + + + @Test + void testGetDAI() throws Exception { + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iAdapter = assertDoesNotThrow(() -> sclRootAdapter.getIEDAdapterByName("IED4d4fe1a8cda64cf88a5ee4176a1a0eef")); + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(()-> iAdapter.getLDeviceAdapterByLdInst("LDSUIED").get()); + LN0Adapter ln0Adapter = lDeviceAdapter.getLN0Adapter(); + ResumedDataTemplate filter = new ResumedDataTemplate(); + filter.setLnClass(ln0Adapter.getLNClass()); + filter.setLnInst(ln0Adapter.getLNInst()); + filter.setPrefix(ln0Adapter.getPrefix()); + filter.setLnType(ln0Adapter.getLnType()); + filter.setDoName(new DoTypeName("Beh")); + DaTypeName daTypeName = new DaTypeName(); + daTypeName.setName("stVal"); + daTypeName.setBType(TPredefinedBasicTypeEnum.ENUM); + daTypeName.setFc(TFCEnum.ST); + filter.setDaName(daTypeName); + var rDtts = ln0Adapter.getDAI(filter,false); + assertFalse(rDtts.isEmpty()); + assertEquals(1,rDtts.size()); + assertNotNull(rDtts.get(0).getDaName().getType()); + } + + @Test + void getEnumValue() throws Exception { + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml"); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iAdapter = assertDoesNotThrow(() -> sclRootAdapter.getIEDAdapterByName("IED4d4fe1a8cda64cf88a5ee4176a1a0eef")); + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(()-> iAdapter.getLDeviceAdapterByLdInst("LDSUIED").get()); + LN0Adapter ln0Adapter = lDeviceAdapter.getLN0Adapter(); + ResumedDataTemplate filter = new ResumedDataTemplate(); + filter.setLnClass(ln0Adapter.getLNClass()); + filter.setLnInst(ln0Adapter.getLNInst()); + filter.setPrefix(ln0Adapter.getPrefix()); + filter.setLnType(ln0Adapter.getLnType()); + filter.setDoName(new DoTypeName("Beh")); + DaTypeName daTypeName = new DaTypeName(); + daTypeName.setName("stVal"); + daTypeName.setBType(TPredefinedBasicTypeEnum.ENUM); + daTypeName.setFc(TFCEnum.ST); + filter.setDaName(daTypeName); + Set enumValues = ln0Adapter.getEnumValue(filter); + assertEquals(5, enumValues.size()); + } } diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test1_LD_STATUS_INACTIVE.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test1_LD_STATUS_INACTIVE.scd new file mode 100644 index 000000000..b6f2124f7 --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test1_LD_STATUS_INACTIVE.scd @@ -0,0 +1,224 @@ + + + + + + + SCD + +

+ + + +
+ + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

00000001

+
+
+ +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+ +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + off + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + on + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + blocked + test + test/blocked + + + off + blocked + test + test/blocked + + + blocked + test + test/blocked + + + \ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test2_LD_STATUS_INACTIVE.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test2_LD_STATUS_INACTIVE.scd new file mode 100644 index 000000000..f94cd1956 --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test2_LD_STATUS_INACTIVE.scd @@ -0,0 +1,222 @@ + + + + + + + SCD + +
+ + + +
+ + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + +
+

00000001

+
+
+ +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+ +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + off + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + on + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + blocked + test + test/blocked + + + on + off + blocked + test + test/blocked + + + on + off + blocked + test + test/blocked + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingBeh.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingBeh.scd new file mode 100644 index 000000000..068f2cf7f --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingBeh.scd @@ -0,0 +1,114 @@ + + + + + + + SCD + +
+ + + +
+ + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + off + + + + + + + + + + + + + + + + + + + + + + + blocked + test + test/blocked + off + on + + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivate.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivate.scd new file mode 100644 index 000000000..48877c0b5 --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivate.scd @@ -0,0 +1,112 @@ + + + + + + + SCD + +
+ + + +
+ + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + off + + + + + + + + + + + + + + + + + + + + + + + + blocked + test + test/blocked + off + on + + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivateAttribute.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivateAttribute.scd new file mode 100644 index 000000000..8ab10e71c --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivateAttribute.scd @@ -0,0 +1,115 @@ + + + + + + + SCD + +
+ + + +
+ + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + off + + + + + + + + + + + + + + + + + + + + + + + + blocked + test + test/blocked + off + on + + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingMod.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingMod.scd new file mode 100644 index 000000000..f6d2f2979 --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_KO_MissingMod.scd @@ -0,0 +1,114 @@ + + + + + + + SCD + +
+ + + +
+ + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + off + + + + + + + + + + + + + + + + + + + + + + + blocked + test + test/blocked + off + on + + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_LD_STATUS_ACTIVE.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_LD_STATUS_ACTIVE.scd new file mode 100644 index 000000000..0823597c2 --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_LD_STATUS_ACTIVE.scd @@ -0,0 +1,219 @@ + + + + + + + SCD + +
+ + + +
+ + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + +
+

00000001

+
+
+ +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+ +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + off + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + on + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + blocked + test + test/blocked + + + off + blocked + test + test/blocked + + + blocked + test + test/blocked + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_LD_STATUS_UNTESTED.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_LD_STATUS_UNTESTED.scd new file mode 100644 index 000000000..6f2cb7e9d --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_LD_STATUS_UNTESTED.scd @@ -0,0 +1,219 @@ + + + + + + + SCD + +
+ + + +
+ + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + +
+

00000001

+
+
+ +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+ +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + off + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + on + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + blocked + test + test/blocked + + + off + blocked + test + test/blocked + + + blocked + test + test/blocked + + +
\ No newline at end of file diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_Template.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_Template.scd new file mode 100644 index 000000000..140e2390d --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_Template.scd @@ -0,0 +1,223 @@ + + + + + + + SCD + +
+ + + +
+ + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + +
+

00000001

+
+
+ +
+

00000001

+
+
+
+ + +
+

Adresse IP du serveur Syslog

+
+
+ +
+

Adresse IP du serveur Syslog

+
+
+
+
+ + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + off + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + on + + + + + + + + + + + SAMU + SAMU + + + + + + + + + + + + + + + + + 01.00.000 + + + 01.00.000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + off + blocked + test + test/blocked + + + on + off + blocked + test + test/blocked + + + on + off + blocked + test + test/blocked + + +
\ No newline at end of file