From c131d24bc0a27b8d2896b541e0095c7ae489e3bf Mon Sep 17 00:00:00 2001 From: massifben <105049157+massifben@users.noreply.github.com> Date: Tue, 25 Oct 2022 16:41:48 +0200 Subject: [PATCH 1/3] fix(78): RSR-437 - add check of source LDevice status Signed-off-by: massifben <105049157+massifben@users.noreply.github.com> --- .../sct/commons/scl/ied/InputsAdapter.java | 21 +++++++++++++------ .../sct/commons/scl/ExtRefServiceTest.java | 8 ++++++- ..._set_extref_iedname_with_extref_errors.xml | 14 +++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapter.java index 8cb5f1a43..bf1991e81 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapter.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapter.java @@ -152,16 +152,25 @@ private Optional validateExtRefSource(TExtRef extRef, IEDAdapter return warningReportItem(extRef, String.format("The signal ExtRef ExtRefldinst does not match any " + "LDevice with same inst attribute in source IED %s", sourceIed.getXPath())); } - Optional optionalLDeviceStatus = sourceLDevice.getLDeviceStatus(); - if (optionalLDeviceStatus.isEmpty()) { + Optional optionalSourceLDeviceStatus = sourceLDevice.getLDeviceStatus(); + if (optionalSourceLDeviceStatus.isEmpty()) { return fatalReportItem(extRef, String.format("The signal ExtRef source LDevice %s status is undefined", sourceLDevice.getXPath())); - } else if (OFF.equals(optionalLDeviceStatus.get())) { - return warningReportItem(extRef, String.format("The signal ExtRef source LDevice %s status is off", - sourceLDevice.getXPath())); } - return Optional.empty(); + return optionalSourceLDeviceStatus.map(sourceLDeviceStatus -> { + switch (sourceLDeviceStatus) { + case OFF: + return SclReportItem.warning(extRefXPath(extRef.getDesc()), String.format("The signal ExtRef source LDevice %s status is off", + sourceLDevice.getXPath())); + case ON: + return null; + default: + return SclReportItem.fatal(extRefXPath(extRef.getDesc()), + String.format("The signal ExtRef source LDevice %s status is neither \"on\" nor \"off\"", + sourceLDevice.getXPath())); + } + }); } private boolean hasMatchingLN(TExtRef extRef, LDeviceAdapter lDeviceAdapter) { diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ExtRefServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ExtRefServiceTest.java index 617ebea50..85372fc6e 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ExtRefServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ExtRefServiceTest.java @@ -108,7 +108,13 @@ public static Stream updateAllExtRefIedNamesErrors() throws Exception SclReportItem.fatal( "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]" + "/LN0/Inputs/ExtRef[@desc=\"Source LDevice is undefined for this ExtRef\"]", - "The signal ExtRef source LDevice /SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST23\"] status is undefined") + "The signal ExtRef source LDevice /SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST23\"] status is " + + "undefined"), + SclReportItem.fatal( + "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]" + + "/LN0/Inputs/ExtRef[@desc=\"Source LDevice is neither on nor off for this ExtRef\"]", + "The signal ExtRef source LDevice /SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST24\"] " + + "status is neither \"on\" nor \"off\"") }), Arguments.of( "Errors on IEDs", diff --git a/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml b/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml index 17b090745..5e9c19b8a 100644 --- a/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml +++ b/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml @@ -31,6 +31,7 @@ + @@ -50,6 +51,8 @@ + + @@ -133,6 +136,17 @@ + + + + + + test + + + + + From b3cd832f60b31878629416ec5b1d1e61325e65f1 Mon Sep 17 00:00:00 2001 From: Aliou DIAITE Date: Wed, 2 Nov 2022 17:05:33 +0100 Subject: [PATCH 2/3] fix(177): filter binding info list from DTT with pLN too Signed-off-by: Aliou DIAITE --- .../sct/commons/dto/ExtRefBindingInfo.java | 33 ++- .../compas/sct/commons/scl/SclService.java | 4 +- .../sct/commons/scl/dtt/DOTypeAdapter.java | 53 ++--- .../scl/dtt/DataTypeTemplateAdapter.java | 93 ++------- .../sct/commons/scl/dtt/LNodeTypeAdapter.java | 22 +- .../commons/scl/ied/AbstractLNAdapter.java | 31 ++- .../sct/commons/scl/ied/LDeviceAdapter.java | 34 ++-- .../sct/commons/scl/ied/LN0Adapter.java | 2 +- .../compas/sct/commons/scl/ied/LNAdapter.java | 2 +- .../commons/dto/ExtRefBindingInfoTest.java | 87 +++++++- .../sct/commons/scl/SclServiceTest.java | 38 ++-- .../commons/scl/dtt/DOTypeAdapterTest.java | 34 +++- .../scl/dtt/DataTypeTemplateAdapterTest.java | 188 +++++++++++++---- .../commons/scl/dtt/LNodeTypeAdapterTest.java | 131 ++++++++++-- .../commons/scl/ied/LDeviceAdapterTest.java | 25 ++- .../sct/commons/scl/ied/LN0AdapterTest.java | 190 +++++++++++++++--- .../sct/commons/scl/ied/LNAdapterTest.java | 80 ++++++-- ...cd_dtt_import_sameid-diff-content-test.xml | 1 - .../scd_get_binders_test.xml | 9 +- 19 files changed, 779 insertions(+), 278 deletions(-) diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ExtRefBindingInfo.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ExtRefBindingInfo.java index 2c1bf56a1..748ac166f 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ExtRefBindingInfo.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ExtRefBindingInfo.java @@ -8,9 +8,11 @@ import lombok.NoArgsConstructor; import lombok.Setter; import org.apache.commons.lang3.StringUtils; -import org.lfenergy.compas.scl2007b4.model.TExtRef; -import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; -import org.lfenergy.compas.scl2007b4.model.TServiceType; +import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.dtt.DATypeAdapter; +import org.lfenergy.compas.sct.commons.scl.dtt.DOTypeAdapter; +import org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter; import java.util.Comparator; import java.util.Objects; @@ -181,4 +183,29 @@ public String toString() { '}'; } + + /** + * updates bindingInfo from given data + * @param signalInfo contains DAType info to set + * @param doTypeInfo contains DOType info leading to DA + * @throws ScdException thrown when inconsistency between DOType and DAType + */ + public void updateDAInfos(ExtRefSignalInfo signalInfo, DataTypeTemplateAdapter.DOTypeInfo doTypeInfo) throws ScdException { + DaTypeName daTypeName = new DaTypeName(signalInfo.getPDA()); + String extDaName = daTypeName.getName(); + DOTypeAdapter lastDoTypeAdapter = doTypeInfo.getDoTypeAdapter(); + TDA da = lastDoTypeAdapter.getDAByName(extDaName).orElseThrow(() -> + new ScdException(String.format("%s: Unknown DA (%s) in DOType (%s) ", doTypeInfo.getDoTypeName(), extDaName, doTypeInfo.getDoTypeId()))); + if (da.getBType() != TPredefinedBasicTypeEnum.STRUCT && !daTypeName.getStructNames().isEmpty() + || da.getBType() == TPredefinedBasicTypeEnum.STRUCT && daTypeName.getStructNames().isEmpty()) { + throw new ScdException(String.format("Invalid ExtRef signal: no coherence between pDO(%s) and pDA(%s)", + signalInfo.getPDO(), signalInfo.getPDA())); + } + String daTypeId = da.getType(); + DATypeAdapter daTypeAdapter = lastDoTypeAdapter.getParentAdapter().getDATypeAdapterById(daTypeId).orElseThrow(() -> + new IllegalArgumentException(String.format("%s: Unknown DA (%s), or no reference to its type", daTypeName, extDaName))); + daTypeAdapter.check(daTypeName); + daTypeName.setFc(da.getFc()); + this.daName = daTypeName; + } } 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 f9dc830c5..5810f491a 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 @@ -264,9 +264,7 @@ public static List getExtRefBinders(SCL scd, String iedName, .build(); // check for signal existence - // The below throws exception if the signal doesn't exist - //TODO: create method which purpose is only ckecking instead of this one - abstractLNAdapter.getExtRefsBySignalInfo(signalInfo); + abstractLNAdapter.isExtRefExist(signalInfo); // find potential binders for the signalInfo return sclRootAdapter.streamIEDAdapters() 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 c2afb9ef7..3b85f4fd1 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 @@ -14,6 +14,7 @@ import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * A representation of the model object @@ -195,13 +196,7 @@ protected String elementXPath() { * @return Boolean value of check result */ public boolean containsDAWithDAName(String da){ - return currentElem.getSDOOrDA() - .stream() - .filter(unNaming -> unNaming.getClass().equals(TDA.class)) - .map(TDA.class::cast) - .anyMatch( - tda -> tda.getName().equals(da) - ); + return getTdaStream().anyMatch(tda -> tda.getName().equals(da)); } /** @@ -210,10 +205,7 @@ public boolean containsDAWithDAName(String da){ * @return Boolean value of check result */ public boolean containsDAWithEnumTypeId(String enumTypeId) { - return currentElem.getSDOOrDA() - .stream() - .filter(unNaming -> unNaming.getClass().equals(TDA.class)) - .map(TDA.class::cast) + return getTdaStream() .anyMatch( tda -> tda.getBType().equals(TPredefinedBasicTypeEnum.ENUM) && tda.getType().equals(enumTypeId) @@ -227,7 +219,7 @@ public boolean containsDAWithEnumTypeId(String enumTypeId) { * @throws ScdException when inconsistency are found in th SCL's * DataTypeTemplate (unknown reference for example). Which should normally not happens. */ - Pair findPathDoType2DA(String daName) throws ScdException { + public Pair findPathDoTypeToDA(String daName) throws ScdException { if(containsDAWithDAName(daName)){ // Attention : Do this check before calling this function // It is not interesting to no have the DO/SDO that references this DoType @@ -266,7 +258,7 @@ Pair findPathDoType2DA(String daName) throws ScdException * @throws ScdException when inconsistency are found in th SCL's * DataTypeTemplate (unknown reference for example). Which should normally not happens. */ - Pair findPathSDO2DA(String sdoName, String daName) throws ScdException { + Pair findPathSDOToDA(String sdoName, String daName) throws ScdException { String errMsg = String.format("No coherence or path between DO/SDO(%s) and DA(%s)", sdoName,daName); Optional opSdo = getSDOByName(sdoName); if(opSdo.isEmpty()) { @@ -280,7 +272,7 @@ Pair findPathSDO2DA(String sdoName, String daName) throws if(doTypeAdapter.containsDAWithDAName(daName)){ return Pair.of(opSdo.get().getName(),doTypeAdapter); } - return doTypeAdapter.findPathDoType2DA(daName); + return doTypeAdapter.findPathDoTypeToDA(daName); } /** @@ -289,10 +281,7 @@ Pair findPathSDO2DA(String sdoName, String daName) throws * @return Boolean value of check result */ public boolean containsDAStructWithDATypeId(String daTypeId) { - return currentElem.getSDOOrDA() - .stream() - .filter(unNaming -> unNaming.getClass().equals(TDA.class)) - .map(TDA.class::cast) + return getTdaStream() .anyMatch( tda -> TPredefinedBasicTypeEnum.STRUCT.equals(tda.getBType()) && tda.getType().equals(daTypeId) @@ -422,12 +411,30 @@ public Optional getSDOByName(String sdoName) { * @return optional of TDA object or empty if unknown DA name */ public Optional getDAByName(String name) { - for(TUnNaming tUnNaming : currentElem.getSDOOrDA()){ - if(tUnNaming.getClass() == TDA.class && ((TDA)tUnNaming).getName().equals(name)){ - return Optional.of((TDA)tUnNaming); - } + TDOType tdoType = currentElem; + if (!containsDAWithDAName(name)) { + tdoType = findPathDoTypeToDA(name) + .getValue() + .getCurrentElem(); } - return Optional.empty(); + return tdoType.getSDOOrDA() + .stream() + .filter(unNaming -> unNaming.getClass().equals(TDA.class) + && ((TDA)unNaming).getName().equals(name)) + .map(TDA.class::cast) + .findFirst(); + } + + /** + * Retrieves all TDA in DOType + * @return stream of TDA + */ + private Stream getTdaStream() { + return getCurrentElem() + .getSDOOrDA() + .stream() + .filter(unNaming -> unNaming.getClass().equals(TDA.class)) + .map(TDA.class::cast); } /** 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 587f1062c..6f6e388cf 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 @@ -4,9 +4,10 @@ package org.lfenergy.compas.sct.commons.scl.dtt; +import lombok.Getter; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.lfenergy.compas.scl2007b4.model.*; -import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.dto.DoTypeName; import org.lfenergy.compas.sct.commons.dto.ExtRefBindingInfo; import org.lfenergy.compas.sct.commons.dto.ExtRefSignalInfo; @@ -214,10 +215,7 @@ public void importEnumType(String thisIEDName, DataTypeTemplateAdapter prvDttAda String newEnumId = prvEnumType.getId(); Optional opRcvEnumTypeAdapter = this.getEnumTypeAdapterById(oldEnumId); - boolean isImportable = false; - if(!opRcvEnumTypeAdapter.isPresent() || !opRcvEnumTypeAdapter.get().hasSameContentAs(prvEnumType)) { - isImportable = true; - } + boolean isImportable = opRcvEnumTypeAdapter.isEmpty() || !opRcvEnumTypeAdapter.get().hasSameContentAs(prvEnumType); if(isImportable && opRcvEnumTypeAdapter.isPresent()){ // same ID, different content @@ -235,10 +233,10 @@ public void importEnumType(String thisIEDName, DataTypeTemplateAdapter prvDttAda } } - // escalate on this DTT + // escalate on this DTT and update all element linked to added EnumType pairOldAndNewEnumId.forEach((oldId, newId) -> { List daTypeAdapters = prvDttAdapter.findDATypesWhichBdaContainsEnumTypeId(oldId); - var bdas = daTypeAdapters.stream() + List bdas = daTypeAdapters.stream() .map(DATypeAdapter::getBdaAdapters) .flatMap(Collection::stream) .map(DATypeAdapter.BDAAdapter::getCurrentElem) @@ -247,7 +245,7 @@ public void importEnumType(String thisIEDName, DataTypeTemplateAdapter prvDttAda .collect(Collectors.toList()); bdas.forEach(tbda -> tbda.setType(newId)); List doTypeAdapters = prvDttAdapter.findDOTypesWhichDAContainsEnumTypeId(oldId); - var tdas = doTypeAdapters.stream() + List tdas = doTypeAdapters.stream() .map(doTypeAdapter -> retrieveSdoOrDA(doTypeAdapter.getCurrentElem().getSDOOrDA(), TDA.class)) .flatMap(Collection::stream) .filter(tda -> TPredefinedBasicTypeEnum.ENUM == tda.getBType() @@ -549,9 +547,7 @@ protected List findLNodeTypesFromDoWithDoTypeId(String doTypeI */ protected String generateDttId(String iedName,String dttId){ final int MAX_LENGTH = 255; - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append(iedName).append("_").append(dttId); - String str = stringBuilder.toString(); + String str = iedName + "_" + dttId; return str.length() <= MAX_LENGTH ? str : str.substring(0,MAX_LENGTH); } @@ -563,80 +559,35 @@ protected String generateDttId(String iedName,String dttId){ * @throws ScdException */ public ExtRefBindingInfo getBinderResumedDTT(String lnType, ExtRefSignalInfo signalInfo) throws ScdException { - ExtRefBindingInfo binder = new ExtRefBindingInfo(); - // LNodeType check LNodeTypeAdapter lNodeTypeAdapter = getLNodeTypeAdapterById(lnType) - .orElseThrow(()-> new ScdException("Unknown LNodeType:" + lnType)); + .orElseThrow(() -> new ScdException("Unknown LNodeType:" + lnType)); if(lNodeTypeAdapter.getLNClass() == null){ log.error("Mandatory lnClass is missing in DTT. This should not happen for valid SCD"); - throw new IllegalArgumentException("lnClass is mandatory for LNodeType in DataTemplate:" + lnType); + throw new IllegalArgumentException("lnClass is mandatory for LNodeType in DataTemplate : " + lnType); } - binder.setLnType(lnType); binder.setLnClass(lNodeTypeAdapter.getLNClass()); - - if(signalInfo.getPDO() == null) { + if (signalInfo.getPDO() == null) { return binder; } // DoType check - DoTypeName doName = new DoTypeName(signalInfo.getPDO()); - String extDoName = doName.getName(); - String doTypeId = lNodeTypeAdapter.getDOTypeId(extDoName) - .orElseThrow(() ->new ScdException("Unknown doName :" + signalInfo.getPDO())); - - DOTypeAdapter doTypeAdapter = getDOTypeAdapterById(doTypeId) - .orElseThrow( - () -> new IllegalArgumentException( - String.format("%s: No referenced to DO id : %s", doName, doTypeId) - ) - ); - - //doTypeAdapter.completeStructuredData(doName); - doTypeAdapter.checkAndCompleteStructData(doName); - binder.setDoName(doName); - - if(signalInfo.getPDA() == null){ + DOTypeInfo doTypeInfo = lNodeTypeAdapter.findMatchingDOType(signalInfo); + binder.setDoName(new DoTypeName(signalInfo.getPDO())); + if (signalInfo.getPDA() == null) { return binder; } - // DaType check - DaTypeName daName = new DaTypeName(signalInfo.getPDA()); - String extDaName = daName.getName(); - DOTypeAdapter lastDoTypeAdapter = doTypeAdapter; - if(!doTypeAdapter.containsDAWithDAName(extDaName)){ - var pair = doTypeAdapter.findPathDoType2DA(extDaName); - lastDoTypeAdapter = pair.getValue(); - } - - TDA da = lastDoTypeAdapter.getDAByName(extDaName) - .orElseThrow( - ()-> new ScdException( - String.format("%s: Unknown DA (%s) in DOType (%s) ", doName, extDaName, doTypeId) - ) - ); - if(da.getBType() != TPredefinedBasicTypeEnum.STRUCT && !daName.getStructNames().isEmpty() ){ - throw new ScdException( - String.format( - "Invalid ExtRef signal: no coherence between pDO(%s) and pDA(%s)", - signalInfo.getPDO(),signalInfo.getPDA() - ) - ); - } - - if(da.getBType() == TPredefinedBasicTypeEnum.STRUCT && !daName.getStructNames().isEmpty()){ - String daTypeId = da.getType(); - DATypeAdapter daTypeAdapter = getDATypeAdapterById(daTypeId) - .orElseThrow( - () -> new IllegalArgumentException( - String.format("%s: Unknown DA (%s), or no reference to its type", daName, extDaName) - ) - ); - daTypeAdapter.check(daName); - daName.setFc(da.getFc()); - binder.setDaName(daName); - } + binder.updateDAInfos(signalInfo, doTypeInfo); return binder; } + + @RequiredArgsConstructor + @Getter + public static class DOTypeInfo { + private final DoTypeName doTypeName; + private final String doTypeId; + private final DOTypeAdapter doTypeAdapter; + } } 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 c10bb1a26..ecfe0510a 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 @@ -12,6 +12,7 @@ import org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum; import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.dto.DoTypeName; +import org.lfenergy.compas.sct.commons.dto.ExtRefSignalInfo; import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; @@ -229,7 +230,7 @@ Pair findPathFromDo2DA(String doName, String daName) throw if(doTypeAdapter.containsDAWithDAName(doName)){ return Pair.of(doName,doTypeAdapter); } - return doTypeAdapter.findPathDoType2DA(daName); + return doTypeAdapter.findPathDoTypeToDA(daName); } @@ -267,7 +268,7 @@ public void check(@NonNull DoTypeName doTypeName, @NonNull DaTypeName daTypeName if(adapterPair.getRight().containsDAWithDAName(daTypeName.getName())){ lastDoTypeAdapter = adapterPair.getValue(); } else { - adapterPair = adapterPair.getRight().findPathDoType2DA(daTypeName.getName()); + adapterPair = adapterPair.getRight().findPathDoTypeToDA(daTypeName.getName()); lastDoTypeAdapter = adapterPair.getValue(); } } @@ -343,4 +344,21 @@ public List getResumedDTTByDoName(DoTypeName doTypeName) { public String getId() { return currentElem.getId(); } + + /** + * Find binded DOType info + * @param signalInfo + * @return DOType info as object contening name, id and adapter + * @throws ScdException throws when DO unknown + */ + public DataTypeTemplateAdapter.DOTypeInfo findMatchingDOType(ExtRefSignalInfo signalInfo) throws ScdException{ + DoTypeName doName = new DoTypeName(signalInfo.getPDO()); + String extDoName = doName.getName(); + String doTypeId = getDOTypeId(extDoName).orElseThrow(() -> + new IllegalArgumentException("Unknown doName :" + signalInfo.getPDO())); + DOTypeAdapter doTypeAdapter = this.getParentAdapter().getDOTypeAdapterById(doTypeId).orElseThrow(() -> + new IllegalArgumentException(String.format("%s: No referenced to DO id : %s, scl file not valid", doName, doTypeId))); + doTypeAdapter.checkAndCompleteStructData(doName); + return new DataTypeTemplateAdapter.DOTypeInfo(doName, doTypeId, doTypeAdapter); + } } 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 09dc91098..e03226ee0 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 @@ -40,9 +40,7 @@ *
  • {@link AbstractLNAdapter#getLNodeName Returns the logical node name LNName = prefix + lnClass + lnInst}
  • * *
  • {@link AbstractLNAdapter#getExtRefs() Returns the value of the TExtRef containment reference list}
  • - * *
  • {@link AbstractLNAdapter#getExtRefs(ExtRefSignalInfo) Returns the value of the TExtRef containment reference list By ExtRefSignalInfo }
  • - *
  • {@link AbstractLNAdapter#getExtRefsBySignalInfo(ExtRefSignalInfo) Returns the value of the TExtRef containment reference list By ExtRefSignalInfo }
  • * *
  • {@link AbstractLNAdapter#getDAI Returns the value of the ResumedDataTemplate containment reference By filter}
  • *
  • {@link AbstractLNAdapter#getDAIValues(ResumedDataTemplate) Returns DAI (sGroup, value) containment reference list By ResumedDataTemplate filter}
  • @@ -226,30 +224,25 @@ public boolean hasInputs() { } /** - * Gets all ExtRefs matches specified ExtRef info without PDA attribute - * - * @param signalInfo ExtRef filter value - * @return list of TExtRef + * Checks for ExtRef signal existence in target LN + * @param signalInfo ExtRef signal data to check */ - public List getExtRefsBySignalInfo(ExtRefSignalInfo signalInfo) { - if (currentElem.getInputs() == null) { - return new ArrayList<>(); - } - - if (signalInfo == null) { - return currentElem.getInputs().getExtRef(); + public void isExtRefExist(ExtRefSignalInfo signalInfo) { + if (currentElem.getInputs() == null || signalInfo == null) { + throw new ScdException("No Inputs for LN or no ExtRef signal to check"); } if (!signalInfo.isValid()) { - throw new IllegalArgumentException("Invalid or missing attributes in ExtRef signal info"); + throw new ScdException("Invalid or missing attributes in ExtRef signal info"); } - return currentElem.getInputs().getExtRef() + boolean extRefExist = currentElem.getInputs().getExtRef() .stream() - .filter(tExtRef -> Objects.equals(signalInfo.getDesc(), tExtRef.getDesc()) && + .anyMatch(tExtRef -> Objects.equals(signalInfo.getDesc(), tExtRef.getDesc()) && Objects.equals(tExtRef.getPDO(), signalInfo.getPDO()) && Objects.equals(signalInfo.getIntAddr(), tExtRef.getIntAddr()) && - Objects.equals(signalInfo.getPServT(), tExtRef.getPServT()) - ) - .collect(Collectors.toList()); + Objects.equals(signalInfo.getPServT(), tExtRef.getPServT())); + if(!extRefExist) { + throw new ScdException("ExtRef signal does not exist in target LN"); + } } /** 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 6fa771a32..3a29496a5 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 @@ -29,7 +29,6 @@ *
      *
    1. Adapter
    2. *
        - *
      • {@link LDeviceAdapter#streamLnAdapters Returns the value of the LNAdapter containment reference list}
      • *
      • {@link LDeviceAdapter#getLN0Adapter Returns the value of the LN0Adapter containment reference list}
      • *
      • {@link LDeviceAdapter#getLNAdapter Returns the value of the LNAdapter reference object By LNClass, inst and prefix}
      • *
      @@ -182,25 +181,20 @@ public LNAdapter getLNAdapter(String lnClass, String lnInst, String prefix) thro */ public List getExtRefBinders(ExtRefSignalInfo signalInfo) { DataTypeTemplateAdapter dttAdapter = parentAdapter.getParentAdapter().getDataTypeTemplateAdapter(); - List potentialBinders = new ArrayList<>(); - - List> lnAdapters = getLNAdaptersInclundigLN0(); - for(AbstractLNAdapter lnAdapter : lnAdapters) { - String lnType = lnAdapter.getLnType(); - try { - ExtRefBindingInfo extRefBindingInfo = dttAdapter.getBinderResumedDTT(lnType,signalInfo); - extRefBindingInfo.setIedName(parentAdapter.getName()); - extRefBindingInfo.setLdInst(currentElem.getInst()); - extRefBindingInfo.setLnClass(lnAdapter.getLNClass()); - extRefBindingInfo.setLnInst(lnAdapter.getLNInst()); - extRefBindingInfo.setPrefix(lnAdapter.getPrefix()); - - potentialBinders.add(extRefBindingInfo); - } catch (ScdException e) { - log.debug("ExRef filtered out: {}", e.getLocalizedMessage()); - } - } - return potentialBinders; + return getLNAdaptersInclundigLN0() + .stream() + .filter(abstractLNAdapter -> StringUtils.isBlank(signalInfo.getPLN()) || abstractLNAdapter.getLNClass().equals(signalInfo.getPLN())) + .map(lnAdapter -> { + String lnType = lnAdapter.getLnType(); + ExtRefBindingInfo extRefBindingInfo = dttAdapter.getBinderResumedDTT(lnType,signalInfo); + extRefBindingInfo.setIedName(parentAdapter.getName()); + extRefBindingInfo.setLdInst(currentElem.getInst()); + extRefBindingInfo.setLnClass(lnAdapter.getLNClass()); + extRefBindingInfo.setLnInst(lnAdapter.getLNInst()); + extRefBindingInfo.setPrefix(lnAdapter.getPrefix()); + return extRefBindingInfo; + }) + .collect(Collectors.toList()); } /** diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LN0Adapter.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/LN0Adapter.java index 0983b28ba..5173e0656 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 @@ -38,7 +38,7 @@ * *
    3. {@link LN0Adapter#getExtRefs() Returns the value of the TExtRef containment reference list}
    4. *
    5. {@link LN0Adapter#getExtRefs(ExtRefSignalInfo) Returns the value of the TExtRef containment reference list By ExtRefSignalInfo }
    6. - *
    7. {@link LN0Adapter#getExtRefsBySignalInfo(ExtRefSignalInfo) Returns the value of the TExtRef containment reference list By ExtRefSignalInfo }
    8. + *
    9. {@link LN0Adapter#isExtRefExist(ExtRefSignalInfo) throws exception when specified signal not found in LN target}
    10. * *
    11. {@link LN0Adapter#getDAI Returns the value of the ResumedDataTemplate containment reference By filter}
    12. *
    13. {@link LN0Adapter#getDAIValues(ResumedDataTemplate) Returns DAI (sGroup, value) containment reference list By ResumedDataTemplate filter}
    14. 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 b79ebeb24..9268e214c 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 @@ -35,7 +35,7 @@ * *
    15. {@link LNAdapter#getExtRefs() Returns the value of the TExtRef containment reference list}
    16. *
    17. {@link LNAdapter#getExtRefs(ExtRefSignalInfo) Returns the value of the TExtRef containment reference list By ExtRefSignalInfo }
    18. - *
    19. {@link LNAdapter#getExtRefsBySignalInfo(ExtRefSignalInfo) Returns the value of the TExtRef containment reference list By ExtRefSignalInfo }
    20. + *
    21. {@link LNAdapter#isExtRefExist(ExtRefSignalInfo) Returns the value of the TExtRef containment reference list By ExtRefSignalInfo }
    22. * *
    23. {@link LNAdapter#getDAI Returns the value of the ResumedDataTemplate containment reference By filter}
    24. *
    25. {@link LNAdapter#getDAIValues(ResumedDataTemplate) Returns DAI (sGroup, value) containment reference list By ResumedDataTemplate filter}
    26. diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ExtRefBindingInfoTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ExtRefBindingInfoTest.java index 68024e00c..4951b53d6 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ExtRefBindingInfoTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ExtRefBindingInfoTest.java @@ -5,11 +5,17 @@ package org.lfenergy.compas.sct.commons.dto; import org.junit.jupiter.api.Test; -import org.lfenergy.compas.scl2007b4.model.TExtRef; -import org.lfenergy.compas.scl2007b4.model.TServiceType; +import org.lfenergy.compas.scl2007b4.model.*; +import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.scl.dtt.DOTypeAdapter; +import org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.sct.commons.dto.DTO.P_DA; +import static org.lfenergy.compas.sct.commons.dto.DTO.P_DO; class ExtRefBindingInfoTest { @@ -144,4 +150,81 @@ void compareTo_should_return_negative_int_when_first_ExtRefBindingInfo_is_minor_ // Then assertThat(result).isNegative(); } + + @Test + void findAndUpdateDAInfos_shouldThrowException_whenDAUnknown() { + //Given + ExtRefBindingInfo bindingInfo = DTO.createExtRefBindingInfo_Source(); + ExtRefSignalInfo signalInfo = DTO.createExtRefSignalInfo(); + + SclRootAdapter sclRootAdapter = new SclRootAdapter("hID","hVersion","hRevision"); + sclRootAdapter.getCurrentElem().setDataTypeTemplates(new TDataTypeTemplates()); + DataTypeTemplateAdapter dttAdapter = assertDoesNotThrow( + sclRootAdapter::getDataTypeTemplateAdapter); + + TDA tda = new TDA(); + tda.setName(P_DA); + tda.setFc(TFCEnum.CF); + tda.setBType(TPredefinedBasicTypeEnum.FLOAT_32); + + TDO tdo= new TDO(); + tdo.setName(P_DO); + tdo.setType("DO1"); + + TDOType tdoType = new TDOType(); + tdoType.setId("DO1"); + tdoType.getSDOOrDA().add(tda); + + TLNodeType tlNodeType = new TLNodeType(); + tlNodeType.setId("ID"); + tlNodeType.getDO().add(tdo); + dttAdapter.getCurrentElem().getDOType().add(tdoType); + DataTypeTemplateAdapter.DOTypeInfo doTypeInfo = new DataTypeTemplateAdapter.DOTypeInfo(new DoTypeName(P_DO), "ID", + dttAdapter.getDOTypeAdapterById("DO1").get()); + //When Then + assertThatThrownBy(() -> bindingInfo.updateDAInfos(signalInfo,doTypeInfo)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage(P_DA+": Unknown DA ("+P_DA+"), or no reference to its type"); + } + + @Test + void findAndUpdateDAInfos_shouldThrowException_whenDANotCoherentWithDO() { + //Given + ExtRefBindingInfo bindingInfo = DTO.createExtRefBindingInfo_Source(); + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPDO("P_DO"); + signalInfo.setPDA("P_DA"); + SclRootAdapter sclRootAdapter = new SclRootAdapter("hID","hVersion","hRevision"); + sclRootAdapter.getCurrentElem().setDataTypeTemplates(new TDataTypeTemplates()); + DataTypeTemplateAdapter dttAdapter = assertDoesNotThrow( + sclRootAdapter::getDataTypeTemplateAdapter); + + TDA tda = new TDA(); + tda.setName("P_DA"); + tda.setFc(TFCEnum.CF); + tda.setBType(TPredefinedBasicTypeEnum.STRUCT); + + TDO tdo= new TDO(); + tdo.setName("P_DO"); + tdo.setType("DO1"); + + TDOType tdoType = new TDOType(); + tdoType.setId("DO1"); + tdoType.getSDOOrDA().add(tda); + + TLNodeType tlNodeType = new TLNodeType(); + tlNodeType.setId("ID"); + tlNodeType.getDO().add(tdo); + + dttAdapter.getCurrentElem().getDOType().add(tdoType); + dttAdapter.getCurrentElem().getLNodeType().add(tlNodeType); + + DOTypeAdapter doTypeAdapter = dttAdapter.getDOTypeAdapterById("DO1").get(); + DataTypeTemplateAdapter.DOTypeInfo doTypeInfo = new DataTypeTemplateAdapter.DOTypeInfo(new DoTypeName("P_DO"), + "ID", doTypeAdapter); + //When Then + assertThatThrownBy(() -> bindingInfo.updateDAInfos(signalInfo,doTypeInfo)) + .isInstanceOf(ScdException.class) + .hasMessage("Invalid ExtRef signal: no coherence between pDO(P_DO) and pDA(P_DA)"); + } } \ 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 f5984077b..b5b9cec05 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 @@ -174,53 +174,45 @@ void testGetExtRefInfo() throws Exception { } @Test - void testGetExtRefBinders() throws Exception { + void getExtRefBinders_shouldThowScdException_whenExtRefNotExist() throws Exception { + //Given SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_binders_test.xml"); - ExtRefSignalInfo signalInfo = createSignalInfo( - "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" - ); - - assertDoesNotThrow( - () -> SclService.getExtRefBinders( - scd, "IED_NAME1", "LD_INST11", "LLN0", "", "", signalInfo - ) - ); - - assertThrows( - ScdException.class, - () -> SclService.getExtRefBinders( - scd, "IED_NAME1", "UNKNOWN_LD", "LLN0", "", "", signalInfo - ) - ); + ExtRefSignalInfo signalInfo = createSignalInfo("Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11"); + signalInfo.setPLN("ANCR"); + //When Then + assertThatThrownBy( + () -> SclService.getExtRefBinders(scd, "IED_NAME1", "UNKNOWN_LD", "LLN0", "", "", signalInfo)) + .isInstanceOf(ScdException.class); } @Test - void test_getExtRefBinders_should_return_sorted_list() throws Exception { + void getExtRefBinders_shouldReturnSortedListBindingInfo_whenExtRefAndDOExist() throws Exception { // Given SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_binders_test.xml"); ExtRefSignalInfo signalInfo = createSignalInfo( "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" ); + signalInfo.setPLN("ANCR"); // When List potentialBinders = SclService.getExtRefBinders(scd, "IED_NAME1", "LD_INST11", "LLN0", "", "", signalInfo); // Then - // Not so relevant because we get a single element list from the XML file + assertThat(potentialBinders).hasSize(4); assertThat(potentialBinders) .extracting(ExtRefBindingInfo::getIedName) - .containsExactly("IED_NAME1"); + .containsExactly("IED_NAME1", "IED_NAME1", "IED_NAME2", "IED_NAME3"); assertThat(potentialBinders) .extracting(ExtRefBindingInfo::getLdInst) - .containsExactly("LD_INST12"); + .containsExactly("LD_INST11", "LD_INST12", "LD_INST22", "LD_INST31"); assertThat(potentialBinders) .extracting(ExtRefBindingInfo::getLnClass) - .containsExactly("LLN0"); + .containsExactly("ANCR", "ANCR", "ANCR", "ANCR"); assertThat(potentialBinders) .extracting(ExtRefBindingInfo::getLnInst) - .containsExactly(""); + .containsExactly("1", "1", "2", "3"); } @Test diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapterTest.java index 589c5ef4f..6a7551e23 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DOTypeAdapterTest.java @@ -5,6 +5,8 @@ package org.lfenergy.compas.sct.commons.scl.dtt; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.dto.DoTypeName; @@ -15,6 +17,7 @@ import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; class DOTypeAdapterTest extends AbstractDTTLevel { @@ -80,18 +83,16 @@ void hasSameContentAs() throws Exception { @Test void testCheckAndCompleteStructData() throws Exception { + //Given DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); DOTypeAdapter doTypeAdapter = assertDoesNotThrow(() ->dttAdapter.getDOTypeAdapterById("DO2").get()); DoTypeName doTypeName = new DoTypeName("Op","origin"); assertDoesNotThrow(() ->doTypeAdapter.checkAndCompleteStructData(doTypeName)); assertEquals(TPredefinedCDCEnum.WYE,doTypeName.getCdc()); - - assertThrows( - ScdException.class, - () ->doTypeAdapter.checkAndCompleteStructData(new DoTypeName("Op","toto")) - ); - + DoTypeName doTypeName1 = new DoTypeName("Op","toto"); + //When Then + assertThatThrownBy(() ->doTypeAdapter.checkAndCompleteStructData(doTypeName1)).isInstanceOf(ScdException.class); } @Test @@ -135,10 +136,10 @@ void testFindPathSDO2DA() throws Exception { AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID ); DOTypeAdapter doTypeAdapter = assertDoesNotThrow(() -> dttAdapter.getDOTypeAdapterById("DO1").get()); - assertThrows(ScdException.class, () -> doTypeAdapter.findPathSDO2DA("origin","unknown")); - assertThrows(ScdException.class, () -> doTypeAdapter.findPathSDO2DA("unknown","antRef")); + assertThrows(ScdException.class, () -> doTypeAdapter.findPathSDOToDA("origin","unknown")); + assertThrows(ScdException.class, () -> doTypeAdapter.findPathSDOToDA("unknown","antRef")); var pair = assertDoesNotThrow( - () -> doTypeAdapter.findPathSDO2DA("origin","antRef") + () -> doTypeAdapter.findPathSDOToDA("origin","antRef") ); assertEquals("d",pair.getKey()); DOTypeAdapter lastDoTypeAdapter = pair.getValue(); @@ -185,4 +186,19 @@ void elementXPath() throws Exception { // Then assertThat(result).isEqualTo("DOType[@id=\"DO1\"]"); } + + @ParameterizedTest + @CsvSource({"angRef,CF,PhaseAngleReferenceKind", "antRef,ST,DA1"}) + void getDAByName(String daName, String fc, String type) throws Exception { + // Given + DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile( + AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); + DOTypeAdapter doTypeAdapter = assertDoesNotThrow(() -> dttAdapter.getDOTypeAdapterById("DO2").get()); + // When + TDA result = assertDoesNotThrow(() -> doTypeAdapter.getDAByName(daName).get()); + // Then + assertThat(result).isNotNull() + .extracting(TDA::getName, TDA::getFc, TDA::getType) + .containsExactlyInAnyOrder(daName,TFCEnum.fromValue(fc),type); + } } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapterTest.java index cc3aed22b..7b8ae510e 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/DataTypeTemplateAdapterTest.java @@ -7,17 +7,21 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.lfenergy.compas.scl2007b4.model.*; -import org.lfenergy.compas.sct.commons.dto.DTO; +import org.lfenergy.compas.sct.commons.dto.ExtRefBindingInfo; import org.lfenergy.compas.sct.commons.dto.ExtRefSignalInfo; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper; +import java.util.Arrays; import java.util.List; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; class DataTypeTemplateAdapterTest { @@ -48,10 +52,9 @@ public void setUp(){ @Test void testAmChildElementRef() { SclRootAdapter sclRootAdapter = dataTypeTemplateAdapter.getParentAdapter(); - assertThrows( - IllegalArgumentException.class, - () ->new DataTypeTemplateAdapter(sclRootAdapter, new TDataTypeTemplates()) - ); + TDataTypeTemplates dtt = new TDataTypeTemplates(); + assertThatThrownBy(() -> new DataTypeTemplateAdapter(sclRootAdapter, dtt)) + .isInstanceOf(IllegalArgumentException.class); } @Test @@ -138,11 +141,6 @@ void testGetEnumTypeAdapters() { assertFalse(dataTypeTemplateAdapter.getEnumTypeAdapters().isEmpty()); } - @Test - void testImportEnumTypes() { - - } - @Test void testHasSameID() { TDAType tdaType1 = new TDAType(); @@ -221,7 +219,29 @@ void testFindDOTypesWhichDAContainsStructWithDATypeId() throws Exception { } @Test - void testRetrieveSdoOrDO() { + void retrieveSdoOrDO_shouldReturnEmptyList() { + //Given + TSDO tsdo = new TSDO(); + TBDA tbda = new TBDA(); + TDA tda = new TDA(); + List list = Arrays.asList(tsdo,tbda,tda); + //When Then + assertThat(DataTypeTemplateAdapter.retrieveSdoOrDA(list, TDO.class)).isEmpty(); + } + + @Test + void retrieveSdoOrDO_shouldReturnListWithTwoElements() { + //Given + TSDO tsdo = new TSDO(); + TDO tdo = new TDO(); + TBDA tbda1 = new TBDA(); + TBDA tbda2 = new TBDA(); + TDA tda = new TDA(); + List list = Arrays.asList(tsdo,tdo,tbda1,tbda2,tda); + //When Then + assertThat(DataTypeTemplateAdapter.retrieveSdoOrDA(list, TBDA.class)) + .hasSize(2) + .hasOnlyElementsOfType(TBDA.class); } @Test @@ -248,29 +268,48 @@ void testFindLNodeTypesFromDoWithDoTypeId() throws Exception { assertTrue(lNodeTypeAdapters.isEmpty()); } - @Test - void testGenerateDttId() { + @ParameterizedTest + @CsvSource({"IED_NAME, DTT_ID, IED_NAME_DTT_ID", + "IED_NAME, Z6A2chUEHc7a15MvIUbQTVvioCgzOcWlNMfOzNbfjLJaueNf9T2GmQP7ShgYFr3SfYex5HdwvC5tRr9oAp0lmSwtqxx1cHEKL" + + "MgKX7hZuUWCpKYPJ3I1fmE7NVIvVOtB1JsIOSGclfQfLGDEFjFG7vIozpkijZ0ugtZSOZuCavC5v5JL58yHO1RWCpYVdMDp4Jh" + + "ChU4YjhAhVGbOykJi0b4pc0saXoqf0q5imWmXiiuMuq0sc25IVA2v0TmCSxJ, " + + "IED_NAME_Z6A2chUEHc7a15MvIUbQTVvioCgzOcWlNMfOzNbfjLJaueNf9T2GmQP7ShgYFr3SfYex5HdwvC5tRr9oAp0lmSwtqx" + + "x1cHEKLMgKX7hZuUWCpKYPJ3I1fmE7NVIvVOtB1JsIOSGclfQfLGDEFjFG7vIozpkijZ0ugtZSOZuCavC5v5JL58yHO1RWCpYVdM" + + "Dp4JhChU4YjhAhVGbOykJi0b4pc0saXoqf0q5imWmXiiuMuq0sc25IVA"}) + void generateDttId_shouldReturnIEdNameWithDTTId_whenBothLessThan255(String iedName, String dttId, String newDTTId) { + assertThat(dataTypeTemplateAdapter.generateDttId(iedName, dttId)).hasSizeLessThan(256) + .isEqualTo(newDTTId); + } @Test - void testImportEnumType() throws Exception { - // + void importEnumTypes_shouldAddNewEnum_whenDifferentContent() throws Exception { + //Given DataTypeTemplateAdapter rcvDttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT); - - DataTypeTemplateAdapter prvDttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT); - int nbEnumType = prvDttAdapter.getEnumTypeAdapters().size(); + DataTypeTemplateAdapter prvDttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); + Optional enumTypeAdapter = rcvDttAdapter.getEnumTypeAdapterById("PhaseAngleReferenceKind"); + int rcvDTTEnumValsSize = enumTypeAdapter.get().getCurrentElem().getEnumVal().size(); + //When rcvDttAdapter.importEnumType("IEDName",prvDttAdapter); - assertEquals(nbEnumType,rcvDttAdapter.getEnumTypeAdapters().size()); - - prvDttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); + Optional rcvEnumTypeAdapter = rcvDttAdapter.getEnumTypeAdapterById("PhaseAngleReferenceKind"); + //Then + assertThat(rcvDttAdapter.getEnumTypeAdapters()) + .hasSize(rcvDTTEnumValsSize + prvDttAdapter.getEnumTypeAdapters().size()); + assertThat(rcvEnumTypeAdapter.get().getCurrentElem().getEnumVal()).hasSize(rcvDTTEnumValsSize); + } + @Test + void importEnumTypes_shouldUpdateExistingEnum_whenSameContent() throws Exception { + //Given + DataTypeTemplateAdapter rcvDttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT); + DataTypeTemplateAdapter prvDttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT); + //When rcvDttAdapter.importEnumType("IEDName",prvDttAdapter); - assertTrue(nbEnumType < rcvDttAdapter.getEnumTypeAdapters().size()); - MarshallerWrapper marshallerWrapper = AbstractDTTLevel.createWrapper(); - System.out.println(marshallerWrapper.marshall(prvDttAdapter.getParentAdapter().getCurrentElem())); - System.out.println(marshallerWrapper.marshall(rcvDttAdapter.getParentAdapter().getCurrentElem())); + //Then + assertThat(rcvDttAdapter.getEnumTypeAdapters()).hasSize(prvDttAdapter.getEnumTypeAdapters().size()); } + @Test void testImportDTT() throws Exception { // @@ -341,33 +380,112 @@ void testImportDAType() throws Exception { System.out.println(marshallerWrapper.marshall(rcvDttAdapter.getParentAdapter().getCurrentElem())); } + @ParameterizedTest + @CsvSource({"A,LN1,No coherence or path between DOType(DO2) and DA(A)", + "antRef,LN1,Invalid ExtRef signal: no coherence between pDO(Op.origin) and pDA(antRef)", + "antRef.origin.ctlVal,LN_Type1,Unknown LNodeType:LN_Type1"}) + void getBinderResumedDTT_shouldThrowScdException_whenDONotContainDA(String pDA, String lnType, String message) throws Exception { + //Given + DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPLN("PIOC"); + signalInfo.setPDO("Op.origin"); + signalInfo.setPDA(pDA); + //When Then + assertThatThrownBy(() -> dttAdapter.getBinderResumedDTT(lnType,signalInfo)) + .isInstanceOf(ScdException.class) + .hasMessage(message); + } + @Test - void testGetBinderResumedDTT() throws Exception { + void getBinderResumedDTT_shouldThrowScdException_whenLnClassNotMatches() throws Exception { + //Given DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); + LNodeTypeAdapter lNodeTypeAdapter = dttAdapter.getLNodeTypeAdapterById("LN1").get(); + lNodeTypeAdapter.getCurrentElem().unsetLnClass(); - ExtRefSignalInfo signalInfo = DTO.createExtRefSignalInfo(); + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPLN("CSWI"); signalInfo.setPDO("Op.origin"); - signalInfo.setPDA("antRef"); + signalInfo.setPDA("antRef.origin.ctlVal"); + //When Then + assertThatThrownBy(() -> dttAdapter.getBinderResumedDTT("LN1",signalInfo)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("lnClass is mandatory for LNodeType in DataTemplate : LN1"); + } + + @Test + void getBinderResumedDTT_shouldThrowScdException_whenDOIdNotFound() throws Exception { + //Given + DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); + + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPLN("PIOC"); + signalInfo.setPDO("Do"); + //When Then + assertThatThrownBy(() -> dttAdapter.getBinderResumedDTT("LN1",signalInfo)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Unknown doName :Do"); + } - assertDoesNotThrow(() -> dttAdapter.getBinderResumedDTT("LN1",signalInfo)); + @Test + void getBinderResumedDTT_shouldReturnBindingInfoWithoutDO_whenSignalPDOEmpty() throws Exception { + //Given + DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPLN("PIOC"); + signalInfo.setPDO(null); + //When Then + ExtRefBindingInfo bindingInfo = assertDoesNotThrow(() -> dttAdapter.getBinderResumedDTT("LN1",signalInfo)); + assertThat(bindingInfo) + .extracting("lnType", "lnClass") + .containsExactlyInAnyOrder("LN1", "PIOC"); + assertThat(bindingInfo.getDoName()).isNull(); } - /*@Test - void testCheckSdoAndDaLink() throws Exception { + @Test + void getBinderResumedDTT_shouldReturnBindingInfoWithoutDA_whenSignalPDAEmpty() throws Exception { + //Given DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); - assertDoesNotThrow(() -> dttAdapter.checkDoAndDaLink("origin","origin")); - assertThrows(ScdException.class, () -> dttAdapter.checkDoAndDaLink("f","origin")); - assertTrue( dttAdapter.checkDoAndDaLink("origin","d").isEmpty()); - }*/ + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPLN("PIOC"); + signalInfo.setPDO("Op.origin"); + signalInfo.setPDA(null); + //When Then + ExtRefBindingInfo bindingInfo = assertDoesNotThrow(() -> dttAdapter.getBinderResumedDTT("LN1",signalInfo)); + assertThat(bindingInfo) + .extracting("lnType", "lnClass") + .containsExactlyInAnyOrder("LN1", "PIOC"); + assertThat(bindingInfo.getDoName()).isNotNull(); + assertThat(bindingInfo.getDaName()).isNull(); + } + + @Test + void getBinderResumedDTT_shouldReturnBindingInfo_whenExist() throws Exception { + //Given + DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); + + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPLN("PIOC"); + signalInfo.setPDO("Op.origin"); + signalInfo.setPDA("antRef.origin.ctlVal"); + //When Then + ExtRefBindingInfo bindingInfo = assertDoesNotThrow(() -> dttAdapter.getBinderResumedDTT("LN1",signalInfo)); + assertThat(bindingInfo) + .extracting("lnType", "lnClass") + .containsExactlyInAnyOrder("LN1", "PIOC"); + } @Test void addPrivate() throws Exception { + //Given DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT_DIFF_CONTENT_SAME_ID); TPrivate tPrivate = new TPrivate(); tPrivate.setType("Private Type"); tPrivate.setSource("Private Source"); + //When Then assertThrows(UnsupportedOperationException.class, () -> dttAdapter.addPrivate(tPrivate)); } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapterTest.java index 09a305bed..e9c932840 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/dtt/LNodeTypeAdapterTest.java @@ -5,21 +5,19 @@ package org.lfenergy.compas.sct.commons.scl.dtt; import org.junit.jupiter.api.Test; -import org.lfenergy.compas.scl2007b4.model.TDO; -import org.lfenergy.compas.scl2007b4.model.TLNodeType; -import org.lfenergy.compas.scl2007b4.model.TPrivate; -import org.lfenergy.compas.sct.commons.dto.DTO; -import org.lfenergy.compas.sct.commons.dto.DaTypeName; -import org.lfenergy.compas.sct.commons.dto.DoTypeName; -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.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.mockito.Mockito; import java.util.ArrayList; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.sct.commons.dto.DTO.P_DO; class LNodeTypeAdapterTest extends AbstractDTTLevel { @Override @@ -148,20 +146,15 @@ void testGetResumedDTTs() throws Exception { void testCheck() throws Exception { DataTypeTemplateAdapter dttAdapter = AbstractDTTLevel.initDttAdapterFromFile(AbstractDTTLevel.SCD_DTT); LNodeTypeAdapter lNodeTypeAdapter = assertDoesNotThrow(() ->dttAdapter.getLNodeTypeAdapterById("LN1").get()); - assertThrows( - ScdException.class, - () -> lNodeTypeAdapter.check(new DoTypeName(""),new DaTypeName("")) - ); - - assertThrows( - ScdException.class, - () -> lNodeTypeAdapter.check(new DoTypeName("do"),new DaTypeName("")) - ); - - assertThrows( - ScdException.class, - () -> lNodeTypeAdapter.check(new DoTypeName("do"),new DaTypeName("da")) - ); + DoTypeName doTypeName1 = new DoTypeName(""); + DaTypeName daTypeName1 = new DaTypeName(""); + assertThatThrownBy(() -> lNodeTypeAdapter.check(doTypeName1,daTypeName1)).isInstanceOf(ScdException.class); + DoTypeName doTypeName2 = new DoTypeName("do"); + DaTypeName daTypeName2 = new DaTypeName(""); + assertThatThrownBy(() -> lNodeTypeAdapter.check(doTypeName2,daTypeName2)).isInstanceOf(ScdException.class); + DoTypeName doTypeName3 = new DoTypeName("do"); + DaTypeName daTypeName3 = new DaTypeName("da"); + assertThatThrownBy(() -> lNodeTypeAdapter.check(doTypeName3,daTypeName3)).isInstanceOf(ScdException.class); DoTypeName doTypeName = new DoTypeName("Op.res"); DaTypeName daTypeName = new DaTypeName("d"); @@ -209,4 +202,100 @@ void elementXPath() throws Exception { // Then assertThat(result).isEqualTo("LNodeType[@id=\"LN1\" and @lnClass=\"PIOC\"]"); } + + @Test + void checkMatchingDOType_shouldFindOneDO() { + //Given + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPDO("P_DO"); + + SclRootAdapter sclRootAdapter = new SclRootAdapter("hID","hVersion","hRevision"); + sclRootAdapter.getCurrentElem().setDataTypeTemplates(new TDataTypeTemplates()); + DataTypeTemplateAdapter dttAdapter = assertDoesNotThrow( + sclRootAdapter::getDataTypeTemplateAdapter); + + TDO tdo= new TDO(); + tdo.setName("P_DO"); + tdo.setType("DO1"); + + TDOType tdoType = new TDOType(); + tdoType.setId("DO1"); + + TLNodeType tlNodeType = new TLNodeType(); + tlNodeType.setId("ID"); + tlNodeType.getDO().add(tdo); + dttAdapter.getCurrentElem().getDOType().add(tdoType); + + dttAdapter.getCurrentElem().getLNodeType().add(tlNodeType); + LNodeTypeAdapter lNodeTypeAdapter = assertDoesNotThrow(() -> dttAdapter.getLNodeTypeAdapterById("ID").get()); + //When + DataTypeTemplateAdapter.DOTypeInfo expectedDoTypeInfo = assertDoesNotThrow(() -> lNodeTypeAdapter.findMatchingDOType(signalInfo)); + //Then + assertThat(expectedDoTypeInfo.getDoTypeId()).isEqualTo("DO1"); + assertThat(expectedDoTypeInfo.getDoTypeName().getName()).isEqualTo("P_DO"); + assertThat(expectedDoTypeInfo.getDoTypeAdapter()).isNotNull(); + + } + + @Test + void checkMatchingDOType_shouldThrowException_whenDOUnknown() { + //Given + ExtRefSignalInfo signalInfo = DTO.createExtRefSignalInfo(); + + SclRootAdapter sclRootAdapter = new SclRootAdapter("hID","hVersion","hRevision"); + sclRootAdapter.getCurrentElem().setDataTypeTemplates(new TDataTypeTemplates()); + DataTypeTemplateAdapter dttAdapter = assertDoesNotThrow( + sclRootAdapter::getDataTypeTemplateAdapter); + + TDO tdo= new TDO(); + tdo.setName(P_DO); + tdo.setType("DO1"); + + TDOType tdoType = new TDOType(); + tdoType.setId("DO1"); + + TLNodeType tlNodeType = new TLNodeType(); + tlNodeType.setId("ID"); + tlNodeType.getDO().add(tdo); + dttAdapter.getCurrentElem().getDOType().add(tdoType); + + dttAdapter.getCurrentElem().getLNodeType().add(tlNodeType); + LNodeTypeAdapter lNodeTypeAdapter = assertDoesNotThrow(() -> dttAdapter.getLNodeTypeAdapterById("ID").get()); + //When Then + assertThatThrownBy(() -> lNodeTypeAdapter.findMatchingDOType(signalInfo)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Unknown doName :"+P_DO); + } + + @Test + void checkMatchingDOType_shouldThrowException_whenDONotReferenced() { + //Given + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPDO("P_DO"); + + SclRootAdapter sclRootAdapter = new SclRootAdapter("hID","hVersion","hRevision"); + sclRootAdapter.getCurrentElem().setDataTypeTemplates(new TDataTypeTemplates()); + DataTypeTemplateAdapter dttAdapter = assertDoesNotThrow( + sclRootAdapter::getDataTypeTemplateAdapter); + + TDO tdo= new TDO(); + tdo.setName("P_DO"); + tdo.setType("DO2"); + + TDOType tdoType = new TDOType(); + tdoType.setId("DO1"); + + TLNodeType tlNodeType = new TLNodeType(); + tlNodeType.setId("ID"); + tlNodeType.getDO().add(tdo); + dttAdapter.getCurrentElem().getDOType().add(tdoType); + + dttAdapter.getCurrentElem().getLNodeType().add(tlNodeType); + LNodeTypeAdapter lNodeTypeAdapter = assertDoesNotThrow(() -> dttAdapter.getLNodeTypeAdapterById("ID").get()); + //When Then + assertThatThrownBy(() -> lNodeTypeAdapter.findMatchingDOType(signalInfo)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("P_DO: No referenced to DO id : DO2, scl file not valid"); + } + } \ No newline at end of file diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapterTest.java index 86b0d045d..bafdefd74 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LDeviceAdapterTest.java @@ -59,13 +59,36 @@ void testGetLNAdapters() { } @Test - void testGetExtRefBinders() { + void getExtRefBinders_shouldReturnExtRefBindingInfo_whenExist() { + //Given LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(()-> iAdapter.getLDeviceAdapterByLdInst("LD_INS2").get()); ExtRefSignalInfo signalInfo = DTO.createExtRefSignalInfo(); signalInfo.setPDO("Do.sdo1"); signalInfo.setPDA("da.bda1.bda2.bda3"); + //When Then + assertDoesNotThrow(()-> lDeviceAdapter.getExtRefBinders(signalInfo)); + assertThat(lDeviceAdapter.getExtRefBinders(signalInfo)).hasSize(1); + } + + @Test + void getExtRefBinders_shouldReturnEmptyList_whenpLNNotMatch() { + //Given + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(()-> iAdapter.getLDeviceAdapterByLdInst("LD_INS2").get()); + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + signalInfo.setPLN("CSWI"); + //When Then + assertDoesNotThrow(()-> lDeviceAdapter.getExtRefBinders(signalInfo)); + assertThat(lDeviceAdapter.getExtRefBinders(signalInfo)).isEmpty(); + } + @Test + void getExtRefBinders_shouldReturnEmptyList_whenpLNNotSet() { + //Given + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(()-> iAdapter.getLDeviceAdapterByLdInst("LD_INS2").get()); + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + //When Then assertDoesNotThrow(()-> lDeviceAdapter.getExtRefBinders(signalInfo)); + assertThat(lDeviceAdapter.getExtRefBinders(signalInfo)).hasSize(2); } @Test 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 6b980c956..f44a7d858 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 @@ -18,6 +18,7 @@ import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; class LN0AdapterTest { @@ -103,32 +104,121 @@ void containsFCDA() { } @Test - void testGetExtRefsBySignalInfo(){ + void isExtRefExist_shouldThrowScdException_whenNoInputsInLN0() { + //Given LDeviceAdapter lDeviceAdapter = Mockito.mock(LDeviceAdapter.class); TLDevice tlDevice = Mockito.mock(TLDevice.class); Mockito.when(lDeviceAdapter.getCurrentElem()).thenReturn(tlDevice); LN0 ln0 = new LN0(); Mockito.when(tlDevice.getLN0()).thenReturn(ln0); - LN0Adapter ln0Adapter = assertDoesNotThrow( () -> new LN0Adapter(lDeviceAdapter,ln0)); + LN0Adapter ln0Adapter = assertDoesNotThrow(() -> new LN0Adapter(lDeviceAdapter, ln0)); + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + //When Then + assertThatThrownBy(() -> ln0Adapter.isExtRefExist(signalInfo)) + .isInstanceOf(ScdException.class) + .hasMessage("No Inputs for LN or no ExtRef signal to check"); + } + + @Test + void isExtRefExist_shouldThrowScdException_whenSignalNotValid() { + //Given + LDeviceAdapter lDeviceAdapter = Mockito.mock(LDeviceAdapter.class); + TLDevice tlDevice = Mockito.mock(TLDevice.class); + Mockito.when(lDeviceAdapter.getCurrentElem()).thenReturn(tlDevice); + LN0 ln0 = new LN0(); + TExtRef tExtRef = new TExtRef(); + TInputs tInputs = new TInputs(); + tInputs.getExtRef().add(tExtRef); + ln0.setInputs(tInputs); + Mockito.when(tlDevice.getLN0()).thenReturn(ln0); + LN0Adapter ln0Adapter = assertDoesNotThrow(() -> new LN0Adapter(lDeviceAdapter, ln0)); + ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); + //When Then + assertThatThrownBy(() -> ln0Adapter.isExtRefExist(signalInfo)) + .isInstanceOf(ScdException.class) + .hasMessage("Invalid or missing attributes in ExtRef signal info"); + } - List extRefList = assertDoesNotThrow(()->ln0Adapter.getExtRefsBySignalInfo(new ExtRefSignalInfo())); - assertTrue(extRefList.isEmpty()); + @Test + void isExtRefExist_shouldThrowScdException_whenSignalNull(){ + //Given + LDeviceAdapter lDeviceAdapter = Mockito.mock(LDeviceAdapter.class); + TLDevice tlDevice = Mockito.mock(TLDevice.class); + Mockito.when(lDeviceAdapter.getCurrentElem()).thenReturn(tlDevice); + LN0 ln0 = new LN0(); TInputs tInputs = new TInputs(); TExtRef extRef = DTO.createExtRef(); tInputs.getExtRef().add(extRef); ln0.setInputs(tInputs); + Mockito.when(tlDevice.getLN0()).thenReturn(ln0); + LN0Adapter ln0Adapter = assertDoesNotThrow( () -> new LN0Adapter(lDeviceAdapter,ln0)); + //When Then + assertThatThrownBy(() -> ln0Adapter.isExtRefExist(null)) + .isInstanceOf(ScdException.class) + .hasMessage("No Inputs for LN or no ExtRef signal to check"); + } - extRefList = assertDoesNotThrow(()->ln0Adapter.getExtRefsBySignalInfo(null)); - assertFalse(extRefList.isEmpty()); + @Test + void isExtRefExist_shouldThrowScdException_whenNotExistInTargetLN(){ + //Given + LDeviceAdapter lDeviceAdapter = Mockito.mock(LDeviceAdapter.class); + TLDevice tlDevice = Mockito.mock(TLDevice.class); + Mockito.when(lDeviceAdapter.getCurrentElem()).thenReturn(tlDevice); + LN0 ln0 = new LN0(); + TInputs tInputs = new TInputs(); + TExtRef extRef = DTO.createExtRef(); + extRef.setPDO("pdo"); + tInputs.getExtRef().add(extRef); + ln0.setInputs(tInputs); + Mockito.when(tlDevice.getLN0()).thenReturn(ln0); + LN0Adapter ln0Adapter = assertDoesNotThrow(() -> new LN0Adapter(lDeviceAdapter, ln0)); + ExtRefSignalInfo signalInfo = DTO.createExtRefSignalInfo(); + //When Then + assertThatThrownBy(() -> ln0Adapter.isExtRefExist(signalInfo)) + .isInstanceOf(ScdException.class) + .hasMessage("ExtRef signal does not exist in target LN"); + } + + @Test + void isExtRefExist_shouldNotThrowException_whenExtRefExist() { + //Given + LDeviceAdapter lDeviceAdapter = Mockito.mock(LDeviceAdapter.class); + TLDevice tlDevice = Mockito.mock(TLDevice.class); + Mockito.when(lDeviceAdapter.getCurrentElem()).thenReturn(tlDevice); + LN0 ln0 = new LN0(); + Mockito.when(tlDevice.getLN0()).thenReturn(ln0); + LN0Adapter ln0Adapter = assertDoesNotThrow(() -> new LN0Adapter(lDeviceAdapter, ln0)); + + TInputs tInputs = new TInputs(); + TExtRef extRef = DTO.createExtRef(); + tInputs.getExtRef().add(extRef); + ln0.setInputs(tInputs); ExtRefSignalInfo signalInfo = DTO.createExtRefSignalInfo(); - extRefList = assertDoesNotThrow(()->ln0Adapter.getExtRefsBySignalInfo(signalInfo)); - assertFalse(extRefList.isEmpty()); + //When Then + assertDoesNotThrow(() -> ln0Adapter.isExtRefExist(signalInfo)); + } - signalInfo.setPDO("Do.papa"); - extRefList = assertDoesNotThrow(()->ln0Adapter.getExtRefsBySignalInfo(signalInfo)); - assertTrue(extRefList.isEmpty()); + @Test + void isExtRefExist_shouldNotThrowException_whenExtRefExistWithPDA() { + //Given + LDeviceAdapter lDeviceAdapter = Mockito.mock(LDeviceAdapter.class); + TLDevice tlDevice = Mockito.mock(TLDevice.class); + Mockito.when(lDeviceAdapter.getCurrentElem()).thenReturn(tlDevice); + LN0 ln0 = new LN0(); + Mockito.when(tlDevice.getLN0()).thenReturn(ln0); + LN0Adapter ln0Adapter = assertDoesNotThrow(() -> new LN0Adapter(lDeviceAdapter, ln0)); + + TInputs tInputs = new TInputs(); + TExtRef extRef = DTO.createExtRef(); + tInputs.getExtRef().add(extRef); + ln0.setInputs(tInputs); + + ExtRefSignalInfo signalInfo = DTO.createExtRefSignalInfo(); + signalInfo.setPDA("Da.papa"); + //When Then + assertDoesNotThrow(() -> ln0Adapter.isExtRefExist(signalInfo)); } @Test @@ -359,32 +449,82 @@ void testGetDAI() throws Exception { } @Test - void getEnumValue() throws Exception { + void getEnumValue_shouldReturnNothing_whenEnumUnknow() throws Exception { + //Given + 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(); + //When + Set enumValues = ln0Adapter.getEnumValues("Behaviour"); + //Then + assertThat(enumValues).isEmpty(); + } + + @Test + void getEnumValue_shouldReturnEnumValues_whenEnumKnown() throws Exception { //Given 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); - daTypeName.setType("BehaviourModeKind"); - filter.setDaName(daTypeName); //When - Set enumValues = ln0Adapter.getEnumValues(filter.getType()); + Set enumValues = ln0Adapter.getEnumValues("BehaviourModeKind"); //Then assertEquals(5, enumValues.size()); assertThat(enumValues).containsExactlyInAnyOrder("blocked", "test", "test/blocked", "off", "on"); } + @Test + void addControlBlock_shouldAddControlBlock_whenReport() throws Exception { + //Given + 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(); + ReportControlBlock reportControlBlock = new ReportControlBlock(); + int reportCBInitSize = ln0Adapter.getCurrentElem().getReportControl().size(); + //When + ln0Adapter.addControlBlock(reportControlBlock); + //Then + assertThat(ln0Adapter.getCurrentElem().getReportControl()).hasSize(reportCBInitSize+1); + } + + @Test + void addControlBlock_shouldAddControlBlock_whenGoose() throws Exception { + //Given + 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(); + GooseControlBlock gooseControlBlock = new GooseControlBlock(); + int reportCBInitSize = ln0Adapter.getCurrentElem().getReportControl().size(); + //When + ln0Adapter.addControlBlock(gooseControlBlock); + //Then + assertThat(ln0Adapter.getCurrentElem().getGSEControl()).hasSize(reportCBInitSize+1); + } + + @Test + void addControlBlock_shouldAddControlBlock_whenSMV() throws Exception { + //Given + 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(); + SMVControlBlock smvControlBlock = new SMVControlBlock(); + int reportCBInitSize = ln0Adapter.getCurrentElem().getReportControl().size(); + //When + ln0Adapter.addControlBlock(smvControlBlock); + //Then + assertThat(ln0Adapter.getCurrentElem().getSampledValueControl()).hasSize(reportCBInitSize+1); + } + @Test void elementXPath() { // Given diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LNAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LNAdapterTest.java index 64d0f02af..2b98eb17b 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LNAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LNAdapterTest.java @@ -79,30 +79,41 @@ void testFindDataSetByRef() { } @Test - void testUpdateExtRefBinders() { + void updateExtRefBindingInfo_shouldUpdateBindingInfo_whenBindingInfoNull() { + //Given ExtRefInfo extRefInfo = DTO.createExtRefInfo(); TExtRef extRef = ExtRefSignalInfo.initExtRef(extRefInfo.getSignalInfo()); - assertNull(extRef.getIedName()); - LNAdapter lnAdapter = initLNAdapter(new TLN()); - extRefInfo.getBindingInfo().setServiceType(null); - lnAdapter.updateExtRefBindingInfo(extRef, extRefInfo); - assertEquals(extRefInfo.getBindingInfo().getServiceType(), extRefInfo.getSignalInfo().getPServT()); - assertEquals(extRefInfo.getBindingInfo().getIedName(), extRef.getIedName()); - assertEquals(extRefInfo.getSourceInfo().getSrcLDInst(), extRef.getSrcLDInst()); - extRefInfo.setBindingInfo(null); extRefInfo.setSourceInfo(null); extRef = ExtRefSignalInfo.initExtRef(extRefInfo.getSignalInfo()); assertNull(extRef.getIedName()); + //When lnAdapter.updateExtRefBindingInfo(extRef, extRefInfo); + //Then assertNull(extRef.getIedName()); assertNull(extRef.getSrcLDInst()); } +@Test + void updateExtRefBindingInfo_shouldUpdateBindingInfo_whenNotBindingInfoNull() { + //Given + ExtRefInfo extRefInfo = DTO.createExtRefInfo(); + TExtRef extRef = ExtRefSignalInfo.initExtRef(extRefInfo.getSignalInfo()); + assertNull(extRef.getIedName()); + LNAdapter lnAdapter = initLNAdapter(new TLN()); + extRefInfo.getBindingInfo().setServiceType(null); + //When + lnAdapter.updateExtRefBindingInfo(extRef, extRefInfo); + //Then + assertEquals(extRefInfo.getBindingInfo().getServiceType(), extRefInfo.getSignalInfo().getPServT()); + assertEquals(extRefInfo.getBindingInfo().getIedName(), extRef.getIedName()); + assertEquals(extRefInfo.getSourceInfo().getSrcLDInst(), extRef.getSrcLDInst()); + } @Test - void testUpdateExtRefBindingInfo() throws Exception { + void updateExtRefBinders_shouldUpdateExtRefs() throws Exception { + //Given SCL scd = SclTestMarshaller.getSCLFromFile("/ied-test-schema-conf/ied_unit_test.xml"); SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iAdapter = assertDoesNotThrow(() -> sclRootAdapter.getIEDAdapterByName("IED_NAME")); @@ -112,22 +123,59 @@ void testUpdateExtRefBindingInfo() throws Exception { .withLnClass("ANCR") .withLnInst("1") .build(); - ExtRefInfo info = DTO.createExtRefInfo(); - assertThrows(ScdException.class, () -> lnAdapter.updateExtRefBinders(info)); - - info.getSignalInfo().setPDO("StrVal.sdo2"); + info.getSignalInfo().setPDO("StrVal.sdo2"); info.getSignalInfo().setPDA("antRef.bda1.bda2.bda3"); info.getSignalInfo().setIntAddr("INT_ADDR2"); info.getSignalInfo().setDesc(null); info.getSignalInfo().setPServT(null); + //When Then assertDoesNotThrow(() -> lnAdapter.updateExtRefBinders(info)); List tExtRefs = lnAdapter.getExtRefs(null); assertEquals(1, tExtRefs.size()); - TExtRef extRef = tExtRefs.get(0); + assertEquals(info.getBindingInfo().getIedName(), tExtRefs.get(0).getIedName()); + + } - assertEquals(info.getBindingInfo().getIedName(), extRef.getIedName()); + @ParameterizedTest(name = "{0}") + @MethodSource("extRefInfoAndMessage") + void updateExtRefBinders_shouldThrowsException(String testCase, ExtRefInfo info, String expectedMessage) throws Exception { + SCL scd = SclTestMarshaller.getSCLFromFile("/ied-test-schema-conf/ied_unit_test.xml"); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iAdapter = assertDoesNotThrow(() -> sclRootAdapter.getIEDAdapterByName("IED_NAME")); + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(() -> iAdapter.getLDeviceAdapterByLdInst("LD_INS2").get()); + LNAdapter lnAdapter = (LNAdapter) AbstractLNAdapter.builder() + .withLDeviceAdapter(lDeviceAdapter) + .withLnClass("ANCR") + .withLnInst("1") + .build(); + assertThatThrownBy(() -> lnAdapter.updateExtRefBinders(info)) + .isInstanceOf(ScdException.class) + .hasMessage(expectedMessage); + } + + private static Stream extRefInfoAndMessage() { + return Stream.of( + Arguments.of("whenBindingInfoNotValid",new ExtRefInfo(), "ExtRef mandatory binding data are missing"), + Arguments.of("whenNoExtRefFound",DTO.createExtRefInfo(), "Unknown ExtRef [pDO(FACntRs1.res),intAddr(INT_ADDR)] in IED_NAME/LD_INST_H.ANCR") + ); + } + + + @Test + void updateExtRefBinders_shouldUpdateExtRefs_whenManyExtRefMatch() { + //Given + TExtRef tExtRef = DTO.createExtRef(); + TInputs inputs = new TInputs(); + inputs.getExtRef().add(tExtRef); + inputs.getExtRef().add(tExtRef); + LN0 ln0 = new LN0(); + ln0.setInputs(inputs); + LN0Adapter ln0Adapter = new LN0Adapter(null, ln0); + ExtRefInfo info = DTO.createExtRefInfo(); + //When Then + assertDoesNotThrow(() ->ln0Adapter.updateExtRefBinders(info)); } diff --git a/sct-commons/src/test/resources/dtt-test-schema-conf/scd_dtt_import_sameid-diff-content-test.xml b/sct-commons/src/test/resources/dtt-test-schema-conf/scd_dtt_import_sameid-diff-content-test.xml index 3f4ff6934..a68ba366b 100644 --- a/sct-commons/src/test/resources/dtt-test-schema-conf/scd_dtt_import_sameid-diff-content-test.xml +++ b/sct-commons/src/test/resources/dtt-test-schema-conf/scd_dtt_import_sameid-diff-content-test.xml @@ -10,7 +10,6 @@ - IEC 61850-7-3:2007B IEC 61850-8-1:2003 diff --git a/sct-commons/src/test/resources/scl-srv-scd-extref-cb/scd_get_binders_test.xml b/sct-commons/src/test/resources/scl-srv-scd-extref-cb/scd_get_binders_test.xml index 4f682d1a3..58ed22b6f 100644 --- a/sct-commons/src/test/resources/scl-srv-scd-extref-cb/scd_get_binders_test.xml +++ b/sct-commons/src/test/resources/scl-srv-scd-extref-cb/scd_get_binders_test.xml @@ -3,7 +3,7 @@ - +
      @@ -12,9 +12,10 @@ - + + @@ -45,6 +46,8 @@ + + @@ -59,6 +62,7 @@ + @@ -80,6 +84,7 @@ + From 742016e09570c772f961d03e8183f40791d67bb6 Mon Sep 17 00:00:00 2001 From: SaintierFr <99645240+SaintierFr@users.noreply.github.com> Date: Thu, 10 Nov 2022 17:05:17 +0100 Subject: [PATCH 3/3] Feat #152: Update SCD creation automation service to call #74 issue (Delete all Control Blocks and Dataset and all ExtRef @srcXXX attributes into a given SCL file) (#182) Signed-off-by: SaintierFr <99645240+SaintierFr@users.noreply.github.com> --- pom.xml | 14 ++ sct-app/pom.xml | 5 + .../compas/sct/app/SclAutomationService.java | 11 +- .../SclAutomationServiceTest.java | 75 +++++- .../commons/scl/ied/AbstractLNAdapter.java | 2 +- .../sct/commons/scl/ied/DAITrackerTest.java | 1 + .../sct/commons/scl/ied/IEDAdapterTest.java | 1 + .../scd-ied-dtt-com-import-stds/ssd.xml | 4 +- .../issue68_Test_Dai_Not_Updatable.scd | 223 ++++++++++++++++++ .../scl-with-control-blocks.xml | 32 ++- 10 files changed, 355 insertions(+), 13 deletions(-) create mode 100644 sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_Dai_Not_Updatable.scd diff --git a/pom.xml b/pom.xml index 9fddeaa9d..314e62a7c 100644 --- a/pom.xml +++ b/pom.xml @@ -157,6 +157,20 @@ + + org.apache.maven.plugins + maven-javadoc-plugin + ${maven.plugin.javadoc} + + + attach-javadocs + package + + aggregate + + + + org.apache.maven.plugins maven-source-plugin diff --git a/sct-app/pom.xml b/sct-app/pom.xml index 1a2857890..46fcaa0f6 100644 --- a/sct-app/pom.xml +++ b/sct-app/pom.xml @@ -60,6 +60,11 @@ 3.6.28 test + + org.assertj + assertj-core + 3.23.1 + diff --git a/sct-app/src/main/java/org/lfenergy/compas/sct/app/SclAutomationService.java b/sct-app/src/main/java/org/lfenergy/compas/sct/app/SclAutomationService.java index 2c35abd29..1b4295c38 100644 --- a/sct-app/src/main/java/org/lfenergy/compas/sct/app/SclAutomationService.java +++ b/sct-app/src/main/java/org/lfenergy/compas/sct/app/SclAutomationService.java @@ -33,9 +33,11 @@ public class SclAutomationService { */ private static final Map, List> comMap = Map.of( Pair.of("RSPACE_PROCESS_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString()), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), - Pair.of("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString()), Arrays.asList("ADMIN_AP","TATA_AP_EFFACEC")); + Pair.of("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString()), Arrays.asList("ADMIN_AP", "TATA_AP_EFFACEC")); - private SclAutomationService(){throw new IllegalStateException("SclAutomationService class"); } + private SclAutomationService() { + throw new UnsupportedOperationException("This is a utility class and cannot be instantiated"); + } /** * Create a SCD file from specified parameters, it calls all functions defined in the process one by one, every step @@ -48,13 +50,14 @@ public class SclAutomationService { */ public static SclRootAdapter createSCD(@NonNull SCL ssd, @NonNull HeaderDTO headerDTO, Set stds) throws ScdException { SclRootAdapter scdAdapter = SclService.initScl(Optional.ofNullable(headerDTO.getId()), - headerDTO.getVersion(),headerDTO.getRevision()); - if(!headerDTO.getHistoryItems().isEmpty()) { + headerDTO.getVersion(), headerDTO.getRevision()); + if (!headerDTO.getHistoryItems().isEmpty()) { HeaderDTO.HistoryItem hItem = headerDTO.getHistoryItems().get(0); SclService.addHistoryItem(scdAdapter.getCurrentElem(), hItem.getWho(), hItem.getWhat(), hItem.getWhy()); } SubstationService.addSubstation(scdAdapter.getCurrentElem(), ssd); SclService.importSTDElementsInSCD(scdAdapter, stds, comMap); + SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scdAdapter.getCurrentElem()); return scdAdapter; } } diff --git a/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceTest.java b/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceTest.java index 84e413104..f5fd66f51 100644 --- a/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceTest.java +++ b/sct-app/src/test/java/org.lfenergy.compas.sct.app/SclAutomationServiceTest.java @@ -6,16 +6,23 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.LN0; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.sct.commons.dto.HeaderDTO; import org.lfenergy.compas.sct.commons.exception.ScdException; +import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; @@ -24,7 +31,7 @@ class SclAutomationServiceTest { private HeaderDTO headerDTO; @BeforeEach - void init(){ + void init() { headerDTO = new HeaderDTO(); headerDTO.setRevision("hRevision"); headerDTO.setVersion("hVersion"); @@ -63,7 +70,7 @@ void createSCD_With_HItem() throws Exception { SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std1, std2, std3)); // Then assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); - assertEquals(1 ,expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); + assertEquals(1, expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size()); assertIsMarshallable(expectedSCD.getCurrentElem()); } @@ -85,7 +92,7 @@ void createSCD_With_HItems() throws Exception { SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml"); SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml"); // When - SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO,Set.of(std1, std2, std3)); + SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std1, std2, std3)); // Then assertNotNull(expectedSCD.getCurrentElem().getHeader().getId()); assertEquals(1, expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size()); @@ -98,8 +105,68 @@ void createSCD_SSD_Without_Substation() throws Exception { // Given SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml"); // When & Then + Set stdListEmpty = new HashSet<>(); assertThrows(ScdException.class, - () -> SclAutomationService.createSCD(ssd, headerDTO, new HashSet<>()) ); + () -> SclAutomationService.createSCD(ssd, headerDTO, stdListEmpty)); + } + + @Test + void createSCD_should_throw_exception_when_null_ssd() throws Exception { + // Given + HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); + historyItem.setWhat("what"); + historyItem.setWho("me"); + historyItem.setWhy("because"); + headerDTO.getHistoryItems().add(historyItem); + SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); + Set stdList = Set.of(std1); + + // When & Then + assertThrows(NullPointerException.class, () -> SclAutomationService.createSCD(null, headerDTO, stdList)); } + @Test + void createSCD_should_throw_exception_when_null_headerDTO() throws Exception { + // Given + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml"); + SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml"); + Set stdList = Set.of(std1); + + // When & Then + assertThrows(NullPointerException.class, () -> SclAutomationService.createSCD(ssd, null, stdList)); + } + + @Test + void createSCD_should_delete_ControlBlocks_DataSet_and_ExtRef_src_attributes() throws Exception { + // Given + SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/ssd.xml"); + SCL std = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml"); + // When + SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std)); + // Then + LN0 ln0 = expectedSCD.streamIEDAdapters() + .findFirst() + .map(iedAdapter -> iedAdapter.getLDeviceAdapterByLdInst("lDeviceInst1").orElseThrow()) + .map(LDeviceAdapter::getLN0Adapter) + .map(SclElementAdapter::getCurrentElem) + .orElseThrow(() -> new RuntimeException("Test shouldn't fail here, please check your XML input file")); + + assertThat(ln0.getDataSet()).isEmpty(); + assertThat(ln0.getInputs().getExtRef()).hasSize(2); + assertFalse(ln0.getInputs().getExtRef().get(0).isSetSrcLDInst()); + assertIsMarshallable(expectedSCD.getCurrentElem()); + } + + @Test + void class_should_not_be_instantiable() { + // Given + Constructor[] constructors = SclAutomationService.class.getDeclaredConstructors(); + assertThat(constructors).hasSize(1); + Constructor constructor = constructors[0]; + constructor.setAccessible(true); + // When & Then + assertThatThrownBy(constructor::newInstance) + .isInstanceOf(InvocationTargetException.class) + .getCause().isInstanceOf(UnsupportedOperationException.class); + } } diff --git a/sct-commons/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 e03226ee0..e18f94b9a 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 @@ -350,7 +350,7 @@ public List> getControlBlocksForMatchingFCDA(@NonNull ExtRefInfo List tDataSets = this.getDataSetMatchingExtRefInfo(extRefInfo); return getControlBlocks(tDataSets, extRefInfo.getBindingInfo().getServiceType()); } - + /** * Gets all Control Blocks from LNode for specified Service Type (GOOSE, SMV and REPORT) and Data Sets * diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/DAITrackerTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/DAITrackerTest.java index 2671ba77b..b220f818d 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/DAITrackerTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/DAITrackerTest.java @@ -12,6 +12,7 @@ import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; class DAITrackerTest { diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapterTest.java index 3d828c3a0..a4d5047f6 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/IEDAdapterTest.java @@ -13,6 +13,7 @@ import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.ObjectReference; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; +import org.lfenergy.compas.sct.commons.scl.com.SubNetworkAdapter; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; import org.mockito.Mockito; diff --git a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/ssd.xml b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/ssd.xml index 4a091c6f5..7488c9a34 100644 --- a/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/ssd.xml +++ b/sct-commons/src/test/resources/scd-ied-dtt-com-import-stds/ssd.xml @@ -6,7 +6,7 @@ --> - SCD + SSD
      @@ -16,7 +16,7 @@ - + diff --git a/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_Dai_Not_Updatable.scd b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_Dai_Not_Updatable.scd new file mode 100644 index 000000000..1de3c1de7 --- /dev/null +++ b/sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_Dai_Not_Updatable.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 diff --git a/sct-commons/src/test/resources/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml b/sct-commons/src/test/resources/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml index 59e826a1d..a192ae121 100644 --- a/sct-commons/src/test/resources/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml +++ b/sct-commons/src/test/resources/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml @@ -4,11 +4,38 @@ - SSD + STD
      + + + +
      +

      0.0.0.0

      +
      +
      +
      + + +
      +

      Adresse IP du serveur Syslog

      +

      udp;tcp;tcp/tls

      +

      Valeur du code de la catégorie des messages

      +

      0.0.0.0

      +

      Nom d utilisateur pour la connexion

      +

      none;hmac-128-sha-224;hmac-192-sha-256;hmac-256-sha-384;hmac-384-sha-512

      +

      Password cle pour l'authentification

      +

      none;aes-cfb-128;aes-cfb-192;aes-cfb-256

      +

      Password cle pour la confidentialite

      +
      +
      +
      +
      - + + + + @@ -42,6 +69,7 @@ +