diff --git a/pom.xml b/pom.xml index 33081daef..9fddeaa9d 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,7 @@ 0.9.1 0.0.4 3.4.1 + 3.2.1 @@ -156,6 +157,20 @@ + + org.apache.maven.plugins + maven-source-plugin + ${maven-source-plugin.version} + + + attach-sources + verify + + jar-no-fork + + + + diff --git a/sct-app/pom.xml b/sct-app/pom.xml index b87bea880..1a2857890 100644 --- a/sct-app/pom.xml +++ b/sct-app/pom.xml @@ -126,6 +126,10 @@ + + org.apache.maven.plugins + maven-source-plugin + - \ No newline at end of file + 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 699994cf2..2c35abd29 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 @@ -5,7 +5,6 @@ package org.lfenergy.compas.sct.app; import lombok.NonNull; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.sct.commons.dto.HeaderDTO; @@ -26,7 +25,6 @@ *
  • {@link SclAutomationService#createSCD(SCL, HeaderDTO, Set) Adds all elements under the SCL object from given SSD and STD files} * */ -@Slf4j public class SclAutomationService { /** diff --git a/sct-app/src/main/resources/logback.xml b/sct-app/src/main/resources/logback.xml deleted file mode 100644 index 9674fe7e4..000000000 --- a/sct-app/src/main/resources/logback.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n - - - - - - - - - - - - \ No newline at end of file diff --git a/sct-commons/pom.xml b/sct-commons/pom.xml index f47ecc126..ea046ce9f 100644 --- a/sct-commons/pom.xml +++ b/sct-commons/pom.xml @@ -218,7 +218,10 @@ - + + org.apache.maven.plugins + maven-source-plugin + diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DataTypeName.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DataTypeName.java index c8f23e8ae..123e5e1ee 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DataTypeName.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/DataTypeName.java @@ -9,7 +9,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -43,7 +42,6 @@ */ @Getter @Setter -@Slf4j @NoArgsConstructor @EqualsAndHashCode public class DataTypeName { @@ -58,7 +56,7 @@ public class DataTypeName { public DataTypeName(String dataName){ if(dataName == null) return; String[] tokens = dataName.split("\\."); - name = tokens[0]; + this.name = tokens[0]; if(tokens.length > 1){ structNames.addAll(List.of(tokens).subList(1, tokens.length)); } 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 6bef42b5c..2c1bf56a1 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 @@ -12,6 +12,7 @@ import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; import org.lfenergy.compas.scl2007b4.model.TServiceType; +import java.util.Comparator; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -39,8 +40,12 @@ @Getter @Setter @NoArgsConstructor -public class ExtRefBindingInfo { +public class ExtRefBindingInfo implements Comparable { + public static final Comparator EXT_REF_BINDING_INFO_COMPARATOR = Comparator.comparing(ExtRefBindingInfo::getIedName) + .thenComparing(ExtRefBindingInfo::getLdInst) + .thenComparing(ExtRefBindingInfo::getLnClass) + .thenComparing(ExtRefBindingInfo::getLnInst); private String iedName; private String ldInst; private String prefix; @@ -53,23 +58,24 @@ public class ExtRefBindingInfo { /** * Constructor + * * @param tExtRef input */ - public ExtRefBindingInfo(TExtRef tExtRef){ + public ExtRefBindingInfo(TExtRef tExtRef) { iedName = tExtRef.getIedName(); ldInst = tExtRef.getLdInst(); prefix = tExtRef.getPrefix(); - if(!tExtRef.getLnClass().isEmpty()) { + if (!tExtRef.getLnClass().isEmpty()) { this.lnClass = tExtRef.getLnClass().get(0); } lnInst = tExtRef.getLnInst(); - if(tExtRef.getDoName() != null) { + if (tExtRef.getDoName() != null) { doName = new DoTypeName(tExtRef.getDoName()); } - if(tExtRef.getDaName() != null) { + if (tExtRef.getDaName() != null) { daName = new DaTypeName(tExtRef.getDaName()); } - if(tExtRef.getServiceType() != null) { + if (tExtRef.getServiceType() != null) { serviceType = tExtRef.getServiceType(); } } @@ -100,33 +106,35 @@ public int hashCode() { /** * Check validity of ExtRef binding information + * * @return validity state */ public boolean isValid() { final String validationRegex = DaTypeName.VALIDATION_REGEX; String doRef = doName == null ? "" : doName.toString(); - Pattern pattern = Pattern.compile(validationRegex,Pattern.MULTILINE); + Pattern pattern = Pattern.compile(validationRegex, Pattern.MULTILINE); Matcher matcher = pattern.matcher(doRef); matcher.find(); - if(!StringUtils.isBlank(doRef) && doRef.length() != matcher.end()){ + if (!StringUtils.isBlank(doRef) && doRef.length() != matcher.end()) { return false; } return !StringUtils.isBlank(iedName) && !StringUtils.isBlank(ldInst) && !StringUtils.isBlank(lnClass) && - (TLLN0Enum.LLN_0.value().equals(lnClass) || !StringUtils.isBlank(lnInst)) ; + (TLLN0Enum.LLN_0.value().equals(lnClass) || !StringUtils.isBlank(lnInst)); } /** * Check dependency between ExtRef binding information and ExtRef + * * @param tExtRef object containing ExtRef data's' * @return dependency state */ - public boolean isWrappedIn(TExtRef tExtRef){ - return Objects.equals(iedName,tExtRef.getIedName()) && - Objects.equals(ldInst,tExtRef.getLdInst()) && + public boolean isWrappedIn(TExtRef tExtRef) { + return Objects.equals(iedName, tExtRef.getIedName()) && + Objects.equals(ldInst, tExtRef.getLdInst()) && Objects.equals(prefix, tExtRef.getPrefix()) && Objects.equals(lnInst, tExtRef.getLnInst()) && tExtRef.getLnClass().contains(lnClass) && @@ -135,9 +143,10 @@ public boolean isWrappedIn(TExtRef tExtRef){ /** * Check nullability of ExtRef binding information - * @return nullability state + * + * @return nullability state */ - public boolean isNull(){ + public boolean isNull() { return iedName == null && ldInst == null && prefix == null && @@ -149,11 +158,18 @@ public boolean isNull(){ } /** - * Convert to string - * @return ExtRef binding information formatted to string + * Define the way to compare 2 objects ExtRefBindingInfo in order to allow sorting items + * + * @param o the object to be compared. + * @return the comparaison's result (a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second) */ + public int compareTo(ExtRefBindingInfo o) { + return EXT_REF_BINDING_INFO_COMPARATOR.compare(this, o); + } + @Override public String toString() { + String sType = serviceType != null ? serviceType.value() : null; return "ExtRefBindingInfo{" + "iedName='" + iedName + '\'' + ", ldInst='" + ldInst + '\'' + @@ -161,7 +177,8 @@ public String toString() { ", lnClass='" + lnClass + '\'' + ", lnInst='" + lnInst + '\'' + ", lnType='" + lnType + '\'' + - ", serviceType=" + serviceType.value() + + ", serviceType=" + sType + '}'; + } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ExtRefInfo.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ExtRefInfo.java index 185897b69..595bfcc06 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ExtRefInfo.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/ExtRefInfo.java @@ -5,10 +5,7 @@ package org.lfenergy.compas.sct.commons.dto; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.NonNull; -import lombok.Setter; +import lombok.*; import org.apache.commons.lang3.StringUtils; import org.lfenergy.compas.scl2007b4.model.TExtRef; import org.lfenergy.compas.scl2007b4.model.TFCDA; @@ -38,6 +35,7 @@ @Getter @Setter @NoArgsConstructor +@AllArgsConstructor public class ExtRefInfo extends LNodeMetaDataEmbedder{ private ExtRefSignalInfo signalInfo; @@ -82,9 +80,10 @@ public static ExtRefInfo from(TExtRef tExtRef, String iedName, String ldInst, * @param tfcda FCDA data object * @return match state */ + //TODO this method should be checked, return if parameter tested are not present in FCDA even if two object are different public boolean matchFCDA(@NonNull TFCDA tfcda){ boolean returnValue = true; - if(AbstractLNAdapter.isNull(tfcda)) { + if(AbstractLNAdapter.isFCDANull(tfcda)) { returnValue = false; } @@ -118,4 +117,25 @@ public boolean matchFCDA(@NonNull TFCDA tfcda){ } return returnValue; } + /** + * Check matching between FCDA and ExtRef information (for external binding) + * Check is done for parameter lDInst(mandatory), lNClass(mandatory), lNInst, prefix doName as pDO(mandatory) and daName as pDA + * present in ExtRef and FCDA + * @param tfcda FCDA data to check compatibilities with ExtRef + * @return true if ExtRef matches FCDA for parameters ahead false otherwise + */ + public boolean checkMatchingFCDA(@NonNull TFCDA tfcda){ + if(bindingInfo == null || signalInfo == null) return false; + FCDAInfo fcdaInfo = new FCDAInfo(tfcda); + FCDAInfo fcdaOfBinding = FCDAInfo.builder() + .ldInst(bindingInfo.getLdInst()) + .lnClass(bindingInfo.getLnClass()) + .lnInst(bindingInfo.getLnInst()) + .prefix(bindingInfo.getPrefix()) + .doName(new DoTypeName(signalInfo.getPDO())) + .daName(new DaTypeName(signalInfo.getPDA())) + .build(); + return fcdaInfo.checkFCDACompatibilitiesForBinding(fcdaOfBinding); + } + } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/FCDAInfo.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/FCDAInfo.java index f156e7596..921e43424 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/FCDAInfo.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/FCDAInfo.java @@ -5,13 +5,15 @@ package org.lfenergy.compas.sct.commons.dto; import com.fasterxml.jackson.annotation.JsonIgnore; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.*; import org.apache.commons.lang3.StringUtils; import org.lfenergy.compas.scl2007b4.model.TFCDA; import org.lfenergy.compas.scl2007b4.model.TFCEnum; +import java.util.Objects; + +import static org.lfenergy.compas.sct.commons.util.Utils.equalsOrBothBlank; + /** * A representation of the model object FCDA. * @@ -33,7 +35,9 @@ */ @Getter @Setter +@AllArgsConstructor @NoArgsConstructor +@Builder public class FCDAInfo { private String dataSet; @@ -53,7 +57,11 @@ public class FCDAInfo { * @param tfcda input */ public FCDAInfo(String dataSet, TFCDA tfcda) { + this(tfcda); this.dataSet = dataSet; + } + + public FCDAInfo(TFCDA tfcda) { fc = tfcda.getFc(); ldInst = tfcda.getLdInst(); prefix = tfcda.getPrefix(); @@ -106,4 +114,18 @@ public TFCDA getFCDA(){ public boolean isValid() { return doName != null && doName.isDefined(); } + + /** + * Checks if two FCDAInfo object match for ldInst, lnInst, lnClass, lnPrefix doName and daName for search of binding control blocks + * @param fcdaInfo FCDA to copare with + * @return true if FCDAs match for binding, otherwise false + */ + public boolean checkFCDACompatibilitiesForBinding(FCDAInfo fcdaInfo) { + return equalsOrBothBlank(getLdInst(), fcdaInfo.getLdInst()) + && equalsOrBothBlank(getPrefix(), fcdaInfo.getPrefix()) + && equalsOrBothBlank(getLnClass(), fcdaInfo.getLnClass()) + && equalsOrBothBlank(getLnInst(), fcdaInfo.getLnInst()) + && Objects.equals(getDoName(), fcdaInfo.getDoName()) + && Objects.equals(getDaName(), fcdaInfo.getDaName()); + } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/IedDTO.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/IedDTO.java index 95d624b57..b3f2128fe 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/IedDTO.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/IedDTO.java @@ -7,10 +7,8 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; -import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; import java.util.HashSet; -import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -52,8 +50,7 @@ public IedDTO(String name){ public static IedDTO from(IEDAdapter iedAdapter, LogicalNodeOptions options) { IedDTO iedDTO = new IedDTO(); iedDTO.name = iedAdapter.getName(); - List lDeviceAdapters = iedAdapter.getLDeviceAdapters(); - iedDTO.lDevices = lDeviceAdapters.stream() + iedDTO.lDevices = iedAdapter.streamLDeviceAdapters() .map(lDeviceAdapter -> LDeviceDTO.from(lDeviceAdapter,options)) .collect(Collectors.toUnmodifiableSet()); 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 c0022cb1d..04cfdabad 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 @@ -10,6 +10,10 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; + +import static org.lfenergy.compas.sct.commons.util.CommonConstants.MOD_DO_NAME; +import static org.lfenergy.compas.sct.commons.util.CommonConstants.STVAL; /** @@ -64,10 +68,18 @@ public static ResumedDataTemplate copyFrom(ResumedDataTemplate dtt){ /** * Checks if DA/DO is updatable - * @return Updatable state + * @return true if updatable, false otherwise */ public boolean isUpdatable(){ - return daName.isDefined() && daName.isUpdatable(); + return isDOModDAstVal() || daName.isDefined() && daName.isUpdatable(); + } + + /** + * Checks if DO is Mod and DA is stVal + * @return true if DO is "Mod" and DA is "stVal", false otherwise + */ + private boolean isDOModDAstVal(){ + return doName.getName().equals(MOD_DO_NAME) && daName.getName().equals(STVAL); } @JsonIgnore @@ -329,4 +341,16 @@ public ResumedDataTemplate setVal(String daiValue) { this.setDaiValues(List.of(newDaiVal)); return this; } + + /** + * Retrieve value of the DAI, if present. If multiples values are found, + * the value with the lowest index is returned. + * @return Return the DAI value with the lowest key from getDaName().getdaiValues() map, + * or empty Optional if this DAI has no value. + */ + public Optional findFirstValue() { + return getDaName().getDaiValues().keySet().stream() + .min(Long::compareTo) + .map(key -> getDaName().getDaiValues().get(key)); + } } 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 index 7a62b4bf0..05103dc8d 100644 --- 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 @@ -12,6 +12,9 @@ import java.util.ArrayList; import java.util.List; +/** + * Report of services which work on the SCD. + */ @AllArgsConstructor @NoArgsConstructor @Setter @@ -19,22 +22,22 @@ @Builder public class SclReport { + /** + * The SCD on which errors were encountered + */ private SclRootAdapter sclRootAdapter; - private List errorDescriptionList = new ArrayList<>(); + /** + * List of errors + */ + private List sclReportItems = new ArrayList<>(); + /** + * + * @return true the service succeeded, false otherwise + */ public boolean isSuccess() { - return errorDescriptionList.isEmpty(); + return sclReportItems.stream().noneMatch(SclReportItem::isFatal); } - @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/dto/SclReportItem.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SclReportItem.java new file mode 100644 index 000000000..84d8cd057 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/dto/SclReportItem.java @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.dto; + +import lombok.AllArgsConstructor; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +@Getter +@EqualsAndHashCode +@AllArgsConstructor +public final class SclReportItem { + private final String xpath; + private final String message; + private final boolean isFatal; + + public static SclReportItem fatal(String xpath, String message) { + return new SclReportItem(xpath, message, true); + } + + public static SclReportItem warning(String xpath, String message) { + return new SclReportItem(xpath, message, false); + } + +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ExtRefService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ExtRefService.java new file mode 100644 index 000000000..cc715f875 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ExtRefService.java @@ -0,0 +1,99 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.scl; + +import lombok.experimental.UtilityClass; +import org.apache.commons.lang3.StringUtils; +import org.lfenergy.compas.scl2007b4.model.SCL; +import org.lfenergy.compas.scl2007b4.model.TCompasICDHeader; +import org.lfenergy.compas.scl2007b4.model.TIED; +import org.lfenergy.compas.sct.commons.dto.SclReport; +import org.lfenergy.compas.sct.commons.dto.SclReportItem; +import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; +import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; +import org.lfenergy.compas.sct.commons.scl.ied.LN0Adapter; +import org.lfenergy.compas.sct.commons.util.PrivateEnum; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +@UtilityClass +public class ExtRefService { + + /** + * Updates iedName attribute of all ExtRefs in the Scd. + * + * @return list of encountered errors + */ + public static SclReport updateAllExtRefIedNames(SCL scd) { + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + List iedErrors = validateIed(sclRootAdapter); + if (!iedErrors.isEmpty()) { + return new SclReport(sclRootAdapter, iedErrors); + } + Map icdSystemVersionToIed = sclRootAdapter.streamIEDAdapters() + .collect(Collectors.toMap( + iedAdapter -> PrivateService.extractCompasPrivate(iedAdapter.getCurrentElem(), TCompasICDHeader.class) + .map(TCompasICDHeader::getICDSystemVersionUUID) + .orElseThrow(), // Value presence is checked by method validateIed called above + Function.identity() + )); + + List extRefErrors = sclRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters) + .filter(LDeviceAdapter::hasLN0) + .map(LDeviceAdapter::getLN0Adapter) + .filter(LN0Adapter::hasInputs) + .map(LN0Adapter::getInputsAdapter) + .map(inputsAdapter -> inputsAdapter.updateAllExtRefIedNames(icdSystemVersionToIed)) + .flatMap(List::stream).collect(Collectors.toList()); + + return new SclReport(sclRootAdapter, extRefErrors); + } + + private static List validateIed(SclRootAdapter sclRootAdapter) { + List iedErrors = new ArrayList<>(checkIedCompasIcdHeaderAttributes(sclRootAdapter)); + iedErrors.addAll(checkIedUnityOfIcdSystemVersionUuid(sclRootAdapter)); + return iedErrors; + } + + private static List checkIedCompasIcdHeaderAttributes(SclRootAdapter sclRootAdapter) { + return sclRootAdapter.streamIEDAdapters() + .map(iedAdapter -> { + Optional compasPrivate = PrivateService.extractCompasPrivate(iedAdapter.getCurrentElem(), TCompasICDHeader.class); + if (compasPrivate.isEmpty()) { + return iedAdapter.buildFatalReportItem(String.format("IED has no Private %s element", PrivateEnum.COMPAS_ICDHEADER.getPrivateType())); + } + if (StringUtils.isBlank(compasPrivate.get().getICDSystemVersionUUID()) + || StringUtils.isBlank(compasPrivate.get().getIEDName())) { + return iedAdapter.buildFatalReportItem(String.format("IED private %s as no icdSystemVersionUUID or iedName attribute", + PrivateEnum.COMPAS_ICDHEADER.getPrivateType())); + } + return null; + } + ).filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + private static List checkIedUnityOfIcdSystemVersionUuid(SclRootAdapter sclRootAdapter) { + Map> systemVersionToIedList = sclRootAdapter.getCurrentElem().getIED().stream() + .collect(Collectors.groupingBy(ied -> PrivateService.extractCompasPrivate(ied, TCompasICDHeader.class) + .map(TCompasICDHeader::getICDSystemVersionUUID) + .orElse(""))); + + return systemVersionToIedList.entrySet().stream() + .filter(entry -> StringUtils.isNotBlank(entry.getKey())) + .filter(entry -> entry.getValue().size() > 1) + .map(entry -> SclReportItem.fatal(entry.getValue().stream() + .map(tied -> new IEDAdapter(sclRootAdapter, tied)) + .map(IEDAdapter::getXPath) + .collect(Collectors.joining(", ")), + "/IED/Private/compas:ICDHeader[@ICDSystemVersionUUID] must be unique" + + " but the same ICDSystemVersionUUID was found on several IED.")) + .collect(Collectors.toList()); + } + +} 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 index 59dc6db7e..4691c650a 100644 --- 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 @@ -8,7 +8,7 @@ import lombok.Setter; import org.apache.commons.lang3.tuple.Pair; import org.lfenergy.compas.scl2007b4.model.TCompasLDeviceStatus; -import org.lfenergy.compas.sct.commons.util.STValEnum; +import org.lfenergy.compas.sct.commons.util.LDeviceStatus; import java.util.List; import java.util.Set; @@ -38,15 +38,15 @@ public LDeviceActivation(List> iedNameLdInstList) { * @param enumValues enum values */ public void checkLDeviceActivationStatus(String iedName, String ldInst, TCompasLDeviceStatus compasLDeviceStatus, Set enumValues) { - if (!enumValues.contains(STValEnum.ON.value) && !enumValues.contains(STValEnum.OFF.value)) { + if (!enumValues.contains(LDeviceStatus.ON) && !enumValues.contains(LDeviceStatus.OFF)) { errorMessage = "The LDevice cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'."; } - if (!enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) { + if (!enumValues.contains(LDeviceStatus.ON) && enumValues.contains(LDeviceStatus.OFF)) { if (isDeclaredInSubstation(iedName, ldInst)) { errorMessage = "The LDevice cannot be set to 'on' but has been selected into SSD."; } else { isUpdatable = true; - newVal = STValEnum.OFF.value; + newVal = LDeviceStatus.OFF; } } if(compasLDeviceStatus.equals(TCompasLDeviceStatus.ACTIVE) || @@ -65,20 +65,20 @@ public void checkLDeviceActivationStatus(String iedName, String ldInst, TCompasL * @param enumValues enum values */ private void checkAuthorisationToActivateLDevice(String iedName, String ldInst, Set enumValues) { - if (!enumValues.contains(STValEnum.OFF.value) && enumValues.contains(STValEnum.ON.value)) { + if (!enumValues.contains(LDeviceStatus.OFF) && enumValues.contains(LDeviceStatus.ON)) { if (isDeclaredInSubstation(iedName, ldInst)) { isUpdatable = true; - newVal = STValEnum.ON.value; + newVal = LDeviceStatus.ON; } else { errorMessage = "The LDevice cannot be set to 'off' but has not been selected into SSD."; } } - if (enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) { + if (enumValues.contains(LDeviceStatus.ON) && enumValues.contains(LDeviceStatus.OFF)) { isUpdatable = true; if (isDeclaredInSubstation(iedName, ldInst)) { - newVal = STValEnum.ON.value; + newVal = LDeviceStatus.ON; } else { - newVal = STValEnum.OFF.value; + newVal = LDeviceStatus.OFF; } } @@ -91,19 +91,19 @@ private void checkAuthorisationToActivateLDevice(String iedName, String ldInst, * @param enumValues enum values */ private void checkAuthorisationToDeactivateLDevice(String iedName, String ldInst, Set enumValues) { - if (!enumValues.contains(STValEnum.OFF.value) && enumValues.contains(STValEnum.ON.value)) { + if (!enumValues.contains(LDeviceStatus.OFF) && enumValues.contains(LDeviceStatus.ON)) { if (isDeclaredInSubstation(iedName, ldInst)) { errorMessage = "The LDevice is not qualified into STD but has been selected into SSD."; } else { errorMessage = "The LDevice cannot be set to 'off' but has not been selected into SSD."; } } - if (enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) { + if (enumValues.contains(LDeviceStatus.ON) && enumValues.contains(LDeviceStatus.OFF)) { if (isDeclaredInSubstation(iedName, ldInst)) { errorMessage = "The LDevice is not qualified into STD but has been selected into SSD."; } else { isUpdatable = true; - newVal = STValEnum.OFF.value; + newVal = LDeviceStatus.OFF; } } } diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/PrivateService.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/PrivateService.java index af6b633d8..aea8bd9c1 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/PrivateService.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/PrivateService.java @@ -5,7 +5,6 @@ package org.lfenergy.compas.sct.commons.scl; import lombok.NonNull; -import lombok.extern.slf4j.Slf4j; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.util.PrivateEnum; @@ -24,19 +23,18 @@ * The following features are supported: *

    *
      - *
    1. {@link PrivateService#getCompasPrivate(TPrivate, Class) + *
    2. {@link PrivateService#extractCompasPrivate(TPrivate, Class) * Returns the value of the TPrivate reference object By class type}
    3. * - *
    4. {@link PrivateService#getCompasPrivates(TBaseElement, Class) + *
    5. {@link PrivateService#extractCompasPrivates(TBaseElement, Class) * Returns the value of the TPrivate containment reference list from given TBaseElement By class type}
    6. * - *
    7. {@link PrivateService#getCompasPrivates(List, Class) + *
    8. {@link PrivateService#extractCompasPrivates(List, Class) * Returns the value of the TPrivate containment reference list from given TPrivate elements By class type} *
    9. *
    * @see org.lfenergy.compas.scl2007b4.model.TPrivate */ -@Slf4j public final class PrivateService { private PrivateService() { @@ -46,14 +44,14 @@ private PrivateService() { private static final ObjectFactory objectFactory = new ObjectFactory(); /** - * Converts each item of given list of Private to list of Private element of type compasClass - * @param tPrivates list of private to convert - * @param compasClass type in which Privates should be - * @return list of formatted Private - * @param Inference parameter stands for wanted type of Privates + * Extract compas element of class compasClass nested in private elements. + * @param tPrivates list of privates to look in + * @param compasClass class of privates to extract + * @return list of compas objects nested in the privates. + * @param Inference parameter stands for class compasClass * @throws ScdException throws when inconsistency between types */ - public static List getCompasPrivates(List tPrivates, Class compasClass) throws ScdException { + public static List extractCompasPrivates(List tPrivates, Class compasClass) throws ScdException { PrivateEnum privateEnum = PrivateEnum.fromClass(compasClass); List compasElements = tPrivates.stream().filter(tPrivate -> privateEnum.getPrivateType().equals(tPrivate.getType())) .map(TAnyContentFromOtherNamespace::getContent).flatMap(List::stream) @@ -75,30 +73,31 @@ public static List getCompasPrivates(List tPrivates, Class c } /** - * Converts all Private of given TBaseElement of type compasClass given as parameter - * @param baseElement TBaseElement contenting Privates - * @param compasClass type in which Privates should be given - * @return list of formatted Private - * @param Inference parameter stands for wanted type of Privates + * Extract compas elements of class compasClass nested in private elements of the given baseElement. + * @param baseElement element where to look for privates + * @param compasClass class of privates to extract + * @return list of compas objects nested in the privates. + * @param Inference parameter stands for class compasClass * @throws ScdException throws when inconsistency between types */ - public static List getCompasPrivates(TBaseElement baseElement, Class compasClass) throws ScdException { + public static List extractCompasPrivates(TBaseElement baseElement, Class compasClass) throws ScdException { if (!baseElement.isSetPrivate()) { return Collections.emptyList(); } - return getCompasPrivates(baseElement.getPrivate(), compasClass); + return extractCompasPrivates(baseElement.getPrivate(), compasClass); } /** - * Converts Private of type compasClass given as parameter - * @param tPrivate Private to check if is in wanted type - * @param compasClass type in which Privates should be given - * @return optional of formatted Private - * @param Inference parameter stands for wanted type of Private - * @throws ScdException throws when inconsistency between types + * Extract a single compas element of class compasClass nested in a private element. + * Throws an exception when there are more than 1 compas element of given compasClass nested inside the private element. + * @param tPrivate private where to look in + * @param compasClass class of privates to extract + * @return list of compas objects nested in the privates. + * @param Inference parameter stands for class compasClass + * @throws ScdException throws when inconsistency between types, or when more than 1 compas element is found */ - public static Optional getCompasPrivate(TPrivate tPrivate, Class compasClass) throws ScdException { - List compasPrivates = getCompasPrivates(Collections.singletonList(tPrivate), compasClass); + public static Optional extractCompasPrivate(TPrivate tPrivate, Class compasClass) throws ScdException { + List compasPrivates = extractCompasPrivates(Collections.singletonList(tPrivate), compasClass); if (compasPrivates.size() > 1) { throw new ScdException(String.format("Expecting maximum 1 element of type %s in private %s, but got %d", compasClass.getName(), tPrivate.getType(), compasPrivates.size())); @@ -109,20 +108,41 @@ public static Optional getCompasPrivate(TPrivate tPrivate, Class compa return Optional.of(compasPrivates.get(0)); } + /** + * Extract a single compas element of class compasClass nested in private elements of a given baseElement. + * Throws an exception when there are more than 1 compas element of given compasClass nested inside privates of the baseElement. + * @param baseElement element where to look for privates + * @param compasClass class of privates to extract + * @return list of compas objects nested in the privates. + * @param Inference parameter stands for class compasClass + * @throws ScdException throws when inconsistency between types, or when more than 1 compas element is found + */ + public static Optional extractCompasPrivate(TBaseElement baseElement, Class compasClass) throws ScdException { + List compasPrivates = extractCompasPrivates(baseElement, compasClass); + if (compasPrivates.size() > 1) { + throw new ScdException(String.format("Expecting maximum 1 private of type %s with 1 element, but found %d", + PrivateEnum.fromClass(compasClass).getPrivateType(), compasPrivates.size())); + } + if (compasPrivates.isEmpty()) { + return Optional.empty(); + } + return Optional.of(compasPrivates.get(0)); + } + /** * Gets Private CompasICDHeader from Private * @param tPrivate Private contenting object to get as CompasICDHeader * @return content of th Private as optional of TCompasICDHeader object * @throws ScdException throws when inconsistency between types */ - public static Optional getCompasICDHeader(TPrivate tPrivate) throws ScdException { - return getCompasPrivate(tPrivate, TCompasICDHeader.class); + public static Optional extractCompasICDHeader(TPrivate tPrivate) throws ScdException { + return extractCompasPrivate(tPrivate, TCompasICDHeader.class); } /** - * Removes specified Private from TBaseElement Privates - * @param baseElement BaseElement contenting Privates - * @param privateEnum enum type of Private to remove + * Removes all privates of type privateEnum from baseElement + * @param baseElement baseElement containing privates + * @param privateEnum enum type of private to remove */ public static void removePrivates(TBaseElement baseElement, @NonNull PrivateEnum privateEnum) { if (baseElement.isSetPrivate()) { 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 1939dc07a..47c07085f 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 @@ -7,6 +7,8 @@ import lombok.Getter; import org.lfenergy.compas.scl2007b4.model.TBaseElement; import org.lfenergy.compas.scl2007b4.model.TPrivate; +import org.lfenergy.compas.sct.commons.dto.SclReportItem; + /** * A representation of the model object * {@link SclElementAdapter SclElementAdapter}. @@ -115,4 +117,12 @@ public String getXPath(){ return parentXpath + "/" + elementXPath(); } + /** + * builds message with message content and currentElement xpath + * @param message message + * @return error description with message and current element xpath + */ + public SclReportItem buildFatalReportItem(String message){ + return SclReportItem.fatal(getXPath(), message); + } } 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 4371d0abb..fd064e433 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 @@ -17,9 +17,7 @@ import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; +import java.util.stream.Stream; /** * A representation of the model object @@ -33,7 +31,7 @@ *
  • {@link SclRootAdapter#getHeaderAdapter Returns the value of the HeaderAdapter reference object}
  • *
  • {@link SclRootAdapter#getSubstationAdapter(String) Returns the value of the SubstationAdapter reference object By nme}
  • *
  • {@link SclRootAdapter#getCommunicationAdapter(boolean) Returns or Adds the value of the CommunicationAdapter reference object}
  • - *
  • {@link SclRootAdapter#getIEDAdapters() Returns the value of the IEDAdapter containment reference list}
  • + *
  • {@link SclRootAdapter#streamIEDAdapters() Returns the value of the IEDAdapter containment reference list}
  • *
  • {@link SclRootAdapter#getIEDAdapterByName(String) Returns the value of the IEDAdapter reference object By name}
  • *
  • {@link SclRootAdapter#getDataTypeTemplateAdapter() Returns the value of the DataTypeTemplateAdapter containment reference list}
  • * @@ -265,12 +263,11 @@ public CommunicationAdapter getCommunicationAdapter(boolean createIfNotExists) t /** * Gets all IEDs from SCL - * @return list of IEDAdapter object as IEDs of SCL + * @return Stream of IEDAdapter object as IEDs of SCL */ - public List getIEDAdapters() { + public Stream streamIEDAdapters() { return currentElem.getIED().stream() - .map(tied -> new IEDAdapter(this,tied)) - .collect(Collectors.toList()); + .map(tied -> new IEDAdapter(this, tied)); } /** 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 1c8f4246f..f9dc830c5 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 @@ -69,6 +69,7 @@ * * * + * * @see org.lfenergy.compas.sct.commons.scl.header.HeaderAdapter * @see org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter * @see org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter @@ -88,8 +89,9 @@ private SclService() { /** * Initialise SCD file with Header and Private SCLFileType - * @param hId optional SCL Header ID, if empty random UUID will be created - * @param hVersion SCL Header Version + * + * @param hId optional SCL Header ID, if empty random UUID will be created + * @param hVersion SCL Header Version * @param hRevision SCL Header Revision * @return SclRootAdapter object as SCD file * @throws ScdException throws when inconsistenc in SCL file @@ -103,10 +105,11 @@ public static SclRootAdapter initScl(Optional hId, String hVersion, String /** * Adds new HistoryItem in SCL file - * @param scd SCL file in which new History should be added - * @param who Who realize the action + * + * @param scd SCL file in which new History should be added + * @param who Who realize the action * @param what What kind of action is realized - * @param why Why this action is done + * @param why Why this action is done * @return SclRootAdapter object as SCD file */ public static SclRootAdapter addHistoryItem(SCL scd, String who, String what, String why) { @@ -118,7 +121,8 @@ public static SclRootAdapter addHistoryItem(SCL scd, String who, String what, St /** * Updates Header of SCL file - * @param scd SCL file in which Header should be updated + * + * @param scd SCL file in which Header should be updated * @param headerDTO Header new values * @return SclRootAdapter object as SCD file */ @@ -152,9 +156,10 @@ public static SclRootAdapter updateHeader(@NonNull SCL scd, @NonNull HeaderDTO h /** * Adds IED in SCL file (Related DataTypeTemplate of SCL is updated also) - * @param scd SCL file in which IED should be added + * + * @param scd SCL file in which IED should be added * @param iedName name of IED to add in SCL - * @param icd ICD containing IED to add and related DataTypeTemplate + * @param icd ICD containing IED to add and related DataTypeTemplate * @return IEDAdapter as added IED * @throws ScdException throws when inconsistency between IED to add and SCL file content */ @@ -165,9 +170,10 @@ public static IEDAdapter addIED(SCL scd, String iedName, SCL icd) throws ScdExce /** * Adds new SubNetworks in SCL file from ICD file - * @param scd SCL file in which SubNetworks should be added + * + * @param scd SCL file in which SubNetworks should be added * @param subNetworks list of SubNetworks DTO contenting SubNetwork and ConnectedAp parameter names - * @param icd ICD file from which SubNetworks functional data are copied from + * @param icd ICD file from which SubNetworks functional data are copied from * @return optional of CommunicationAdapter object as Communication node of SCL file. * Calling getParentAdapter() will give SCL file * @throws ScdException throws when no Communication in SCL and createIfNotExists == false @@ -188,8 +194,7 @@ public static Optional addSubnetworks(SCL scd, Set subNetworkAdapter = communicationAdapter.getSubnetworkByName(snName); if (subNetworkAdapter.isPresent()) { - ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.get() - .getConnectedAPAdapter(iedName, apName); + ConnectedAPAdapter connectedAPAdapter = subNetworkAdapter.get().getConnectedAPAdapter(iedName, apName); connectedAPAdapter.copyAddressAndPhysConnFromIcd(icd); } @@ -202,6 +207,7 @@ public static Optional addSubnetworks(SCL scd, SetSubNetworkDTO from SCL * @throws ScdException throws when no Communication in SCL and createIfNotExists == false @@ -209,17 +215,17 @@ public static Optional addSubnetworks(SCL scd, Set getSubnetwork(SCL scd) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); CommunicationAdapter communicationAdapter = sclRootAdapter.getCommunicationAdapter(false); - return communicationAdapter.getSubNetworkAdapters() - .stream() + return communicationAdapter.getSubNetworkAdapters().stream() .map(SubNetworkDTO::from) .collect(Collectors.toList()); } /** * Gets all ExtRef from specific IED/LDevice in SCL file - * @param scd SCL file in which ExtRefs should be found + * + * @param scd SCL file in which ExtRefs should be found * @param iedName name of IED in which LDevice is localized - * @param ldInst LdInst of LDevice in which all ExtRefs should be found + * @param ldInst LdInst of LDevice in which all ExtRefs should be found * @return list of ExtRefInfo from specified parameter SCL/IED/LDevice * @throws ScdException throws when unknown specified IED or LDevice */ @@ -228,32 +234,28 @@ public static List getExtRefInfo(SCL scd, String iedName, String ldI SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) - .orElseThrow( - () -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName)) - ); + .orElseThrow(() -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName))); return lDeviceAdapter.getExtRefInfo(); } /** * Gets all possible ExtRefs to bind in SCL file with given ExtRef (signalInfo) in SCL file - * @param scd SCL file in which ExtRefs should be found - * @param iedName name of IED in which LDevice is localized - * @param ldInst ldInst of LDevice in which LN is localized - * @param lnClass lnClass of LN in which ExtRef signal to find binders is localized - * @param lnInst lnInst of LN in which ExtRef signal to find binders is localized - * @param prefix prefix of LN in which ExtRef signal to find binders is localized + * + * @param scd SCL file in which ExtRefs should be found + * @param iedName name of IED in which LDevice is localized + * @param ldInst ldInst of LDevice in which LN is localized + * @param lnClass lnClass of LN in which ExtRef signal to find binders is localized + * @param lnInst lnInst of LN in which ExtRef signal to find binders is localized + * @param prefix prefix of LN in which ExtRef signal to find binders is localized * @param signalInfo ExtRef signal for which we should find possible binders in SCL file binders - * @return list of ExtRefBindingInfo object (containing binding data for each LNode in current SCL file) + * @return list of ExtRefBindingInfo object (containing binding data for each LNode in current SCL file) sorted by {@link ExtRefBindingInfo#compareTo(ExtRefBindingInfo) compareTo} method. * @throws ScdException throws when ExtRef contains inconsistency data */ - public static List getExtRefBinders(SCL scd, String iedName, String ldInst, - String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException { + public static List getExtRefBinders(SCL scd, String iedName, String ldInst, String lnClass, String lnInst, String prefix, ExtRefSignalInfo signalInfo) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) - .orElseThrow( - () -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName)) - ); + .orElseThrow(() -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName))); AbstractLNAdapter abstractLNAdapter = AbstractLNAdapter.builder() .withLDeviceAdapter(lDeviceAdapter) .withLnClass(lnClass) @@ -263,19 +265,21 @@ public static List getExtRefBinders(SCL scd, String iedName, // 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); // find potential binders for the signalInfo - List potentialBinders = new ArrayList<>(); - for (IEDAdapter iedA : sclRootAdapter.getIEDAdapters()) { - potentialBinders.addAll(iedA.getExtRefBinders(signalInfo)); - } - return potentialBinders; + return sclRootAdapter.streamIEDAdapters() + .map(iedAdapter1 -> iedAdapter1.getExtRefBinders(signalInfo)) + .flatMap(Collection::stream) + .sorted() + .collect(Collectors.toList()); } /** * Updates ExtRef binding data related to given ExtRef (extRefInfo) in given SCL file - * @param scd SCL file in which ExtRef to update should be found + * + * @param scd SCL file in which ExtRef to update should be found * @param extRefInfo ExtRef signal for which we should find possible binders in SCL file * @throws ScdException throws when mandatory data of ExtRef are missing */ @@ -288,13 +292,7 @@ public static void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws Sc SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) - .orElseThrow( - () -> new ScdException( - String.format( - UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName - ) - ) - ); + .orElseThrow(() -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName))); AbstractLNAdapter abstractLNAdapter = AbstractLNAdapter.builder() .withLDeviceAdapter(lDeviceAdapter) @@ -308,7 +306,8 @@ public static void updateExtRefBinders(SCL scd, ExtRefInfo extRefInfo) throws Sc /** * Gets all Control Blocks related to extRefInfo in given SCL file - * @param scd SCL file in which ControlBlocks should be found + * + * @param scd SCL file in which ControlBlocks should be found * @param extRefInfo ExtRef signal for which we should find related ControlBlocks * @return list of ControlBlock object as ControlBlocks of LNode specified in extRefInfo * @throws ScdException throws when mandatory data of ExtRef are missing @@ -329,43 +328,26 @@ public static List> getExtRefSourceInfo(SCL scd, ExtRefInfo extR throw new ScdException("Internal binding can't have control block"); } - String ldInst = extRefInfo.getHolderLDInst(); - String lnClass = extRefInfo.getHolderLnClass(); - String lnInst = extRefInfo.getHolderLnInst(); - String prefix = extRefInfo.getHolderLnPrefix(); - // Check holder (IED,LD,LN) exists SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); - LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) - .orElseThrow( - () -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName)) - ); - AbstractLNAdapter abstractLNAdapter = AbstractLNAdapter.builder() - .withLDeviceAdapter(lDeviceAdapter) - .withLnClass(lnClass) - .withLnInst(lnInst) - .withLnPrefix(prefix) - .build(); - - abstractLNAdapter.checkExtRefInfoCoherence(extRefInfo); // Get CBs IEDAdapter srcIEDAdapter = sclRootAdapter.getIEDAdapterByName(bindingInfo.getIedName()); LDeviceAdapter srcLDeviceAdapter = srcIEDAdapter.getLDeviceAdapterByLdInst(extRefInfo.getBindingInfo().getLdInst()) .orElseThrow(); - AbstractLNAdapter srcLnAdapter = AbstractLNAdapter.builder() - .withLDeviceAdapter(srcLDeviceAdapter) - .withLnClass(extRefInfo.getBindingInfo().getLnClass()) - .withLnInst(extRefInfo.getBindingInfo().getLnInst()) - .withLnPrefix(extRefInfo.getBindingInfo().getPrefix()) - .build(); - return srcLnAdapter.getControlSetByExtRefInfo(extRefInfo); + List> aLNAdapters = srcLDeviceAdapter.getLNAdaptersInclundigLN0(); + + return aLNAdapters.stream() + .map(abstractLNAdapter1 -> abstractLNAdapter1.getControlBlocksForMatchingFCDA(extRefInfo)) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } /** * Updates ExtRef source binding data's based on given data in extRefInfo - * @param scd SCL file in which ExtRef source data's to update should be found + * + * @param scd SCL file in which ExtRef source data's to update should be found * @param extRefInfo new data for ExtRef source binding data * @return TExtRef object as update ExtRef with new source binding data * @throws ScdException throws when mandatory data of ExtRef are missing @@ -396,9 +378,7 @@ public static TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) - .orElseThrow( - () -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName)) - ); + .orElseThrow(() -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName))); var anLNAdapter = AbstractLNAdapter.builder() .withLDeviceAdapter(lDeviceAdapter) .withLnClass(lnClass) @@ -411,34 +391,33 @@ public static TExtRef updateExtRefSource(SCL scd, ExtRefInfo extRefInfo) throws /** * Gets a list of summarized DataTypeTemplate for DataAttribute DA (updatable or not) related to the one given * in rDtt - * @param scd SCL file in which DataTypeTemplate of DAIs should be found - * @param iedName name of IED in which DAs are localized - * @param ldInst ldInst of LDevice in which DAIs are localized - * @param rDtt reference summarized DataTypeTemplate related to IED DAIs + * + * @param scd SCL file in which DataTypeTemplate of DAIs should be found + * @param iedName name of IED in which DAs are localized + * @param ldInst ldInst of LDevice in which DAIs are localized + * @param rDtt reference summarized DataTypeTemplate related to IED DAIs * @param updatable true to retrieve DataTypeTemplate's related to only updatable DAIs, false to retrieve all * @return List of resumed DataTypeTemplate for DataAttribute (updatable or not) * @throws ScdException SCD illegal arguments exception, missing mandatory data */ - public static Set getDAI(SCL scd, String iedName, String ldInst, - ResumedDataTemplate rDtt, boolean updatable) throws ScdException { + public static Set getDAI(SCL scd, String iedName, String ldInst, ResumedDataTemplate rDtt, boolean updatable) throws ScdException { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iedAdapter = new IEDAdapter(sclRootAdapter, iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) - .orElseThrow( - () -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName)) - ); + .orElseThrow(() -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName))); return lDeviceAdapter.getDAI(rDtt, updatable); } /** * Updates DAI based on given data in rDtt - * @param scd SCL file in which DataTypeTemplate of DAI should be found + * + * @param scd SCL file in which DataTypeTemplate of DAI should be found * @param iedName name of IED in which DAI is localized - * @param ldInst ldInst of LDevice in which DAI is localized - * @param rDtt reference summarized DataTypeTemplate related to DAI to update + * @param ldInst ldInst of LDevice in which DAI is localized + * @param rDtt reference summarized DataTypeTemplate related to DAI to update * @throws ScdException when inconsistency are found in th SCL's - * DataTypeTemplate. Which should normally not happens. + * DataTypeTemplate. Which should normally not happens. */ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedDataTemplate rDtt) throws ScdException { long startTime = System.nanoTime(); @@ -457,9 +436,7 @@ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedData IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(ldInst) - .orElseThrow( - () -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName)) - ); + .orElseThrow(() -> new ScdException(String.format(UNKNOWN_LDEVICE_S_IN_IED_S, ldInst, iedName))); AbstractLNAdapter lnAdapter = AbstractLNAdapter.builder() .withLDeviceAdapter(lDeviceAdapter) @@ -478,7 +455,8 @@ public static void updateDAI(SCL scd, String iedName, String ldInst, ResumedData /** * Gets EnumTypes values of ID idEnum from DataTypeTemplate of SCL file - * @param scd SCL file in which EnumType should be found + * + * @param scd SCL file in which EnumType should be found * @param idEnum ID of EnumType for which values are retrieved * @return list of couple EnumType value and it's order * @throws ScdException throws when unkonown EnumType @@ -506,21 +484,21 @@ public static Set> getEnumTypeElements(SCL scd, String idE *
  • import /IED /DataTypeTemplate from that STD file and update IEDName of /IED in SCD file
  • *
  • import connectedAP and rename ConnectedAP/@iedName in Communication node in SCD file
  • * + * * @param scdRootAdapter adapter object related to SCL file in which content of STD files are imported - * @param stds list of STD files contenting datas to import into SCD - * @param comMap couple of Subnetwork name and possible corresponding ConnectAP names + * @param stds list of STD files contenting datas to import into SCD + * @param comMap couple of Subnetwork name and possible corresponding ConnectAP names * @return updated SCD file as SclRootAdapter * @throws ScdException throws when inconsistency between Substation of SCL content and gien STD files as : - *
      - *
    • ICD_SYSTEM_VERSION_UUID in IED/Private of STD is not present in COMPAS-ICDHeader in Substation/../LNode of SCL
    • - *
    • There are several STD files corresponding to ICD_SYSTEM_VERSION_UUID of COMPAS-ICDHeader in Substation/../LNode of SCL
    • - *
    • There is no STD file found corresponding to COMPAS-ICDHeader in Substation/../LNode of SCL
    • - *
    • COMPAS-ICDHeader is not the same in Substation/../LNode of SCL and in IED/Private of STD
    • - *
    • COMPAS_ICDHEADER in Substation/../LNode of SCL not found in IED/Private of STD
    • - *
    + *
      + *
    • ICD_SYSTEM_VERSION_UUID in IED/Private of STD is not present in COMPAS-ICDHeader in Substation/../LNode of SCL
    • + *
    • There are several STD files corresponding to ICD_SYSTEM_VERSION_UUID of COMPAS-ICDHeader in Substation/../LNode of SCL
    • + *
    • There is no STD file found corresponding to COMPAS-ICDHeader in Substation/../LNode of SCL
    • + *
    • COMPAS-ICDHeader is not the same in Substation/../LNode of SCL and in IED/Private of STD
    • + *
    • COMPAS_ICDHEADER in Substation/../LNode of SCL not found in IED/Private of STD
    • + *
    */ - public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdRootAdapter, Set stds, - Map, List> comMap) throws ScdException { + public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdRootAdapter, Set stds, Map, List> comMap) throws ScdException { //Check SCD and STD compatibilities Map>> mapICDSystemVersionUuidAndSTDFile = createMapICDSystemVersionUuidAndSTDFile(stds); @@ -531,8 +509,8 @@ public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdR for (Map.Entry entry : mapIEDNameAndPrivate.entrySet()) { String iedName = entry.getKey(); TPrivate tPrivate = entry.getValue(); - String icdSysVerUuid = PrivateService.getCompasICDHeader(tPrivate).map(TCompasICDHeader::getICDSystemVersionUUID).orElseThrow( - () -> new ScdException(ICD_SYSTEM_VERSION_UUID + " is not present in COMPAS-ICDHeader in LNode") + String icdSysVerUuid = PrivateService.extractCompasICDHeader(tPrivate).map(TCompasICDHeader::getICDSystemVersionUUID) + .orElseThrow(() -> new ScdException(ICD_SYSTEM_VERSION_UUID + " is not present in COMPAS-ICDHeader in LNode") ); if (!mapICDSystemVersionUuidAndSTDFile.containsKey(icdSysVerUuid)) @@ -557,10 +535,11 @@ public static SclRootAdapter importSTDElementsInSCD(@NonNull SclRootAdapter scdR /** * Checks SCD and STD compatibilities by checking if there is at least one ICD_SYSTEM_VERSION_UUID in - * Substation/../LNode/Private COMPAS-ICDHeader of SCL not present in IED/Private COMPAS-ICDHeader of STD + * Substation/../LNode/Private COMPAS-ICDHeader of SCL not present in IED/Private COMPAS-ICDHeader of STD + * * @param mapICDSystemVersionUuidAndSTDFile map of ICD_SYSTEM_VERSION_UUID and list of corresponding STD * @throws ScdException throws when there are several STD files corresponding to ICD_SYSTEM_VERSION_UUID - * from Substation/../LNode/Private COMPAS-ICDHeader of SCL + * from Substation/../LNode/Private COMPAS-ICDHeader of SCL */ private static void checkSTDCorrespondanceWithLNodeCompasICDHeader(Map>> mapICDSystemVersionUuidAndSTDFile) throws ScdException { for (Pair> pairOfPrivateAndSTDs : mapICDSystemVersionUuidAndSTDFile.values()) { @@ -573,20 +552,22 @@ private static void checkSTDCorrespondanceWithLNodeCompasICDHeader(Map optionalCompasICDHeader = PrivateService.getCompasICDHeader(key); - return HEADER_ID + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getHeaderId).orElse(null) + - HEADER_VERSION + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getHeaderVersion).orElse(null) + - HEADER_REVISION + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getHeaderRevision).orElse(null) + - "and " + ICD_SYSTEM_VERSION_UUID + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getICDSystemVersionUUID).orElse(null); + Optional optionalCompasICDHeader = PrivateService.extractCompasICDHeader(key); + return HEADER_ID + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getHeaderId).orElse(null) + " " + + HEADER_VERSION + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getHeaderVersion).orElse(null) + " " + + HEADER_REVISION + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getHeaderRevision).orElse(null) + + " and " + ICD_SYSTEM_VERSION_UUID + " = " + optionalCompasICDHeader.map(TCompasICDHeader::getICDSystemVersionUUID).orElse(null); } /** * Creates map of IEDName and related Private for all Privates COMPAS-ICDHeader in /Substation of SCL + * * @param scdRootAdapter SCL file in which Private should be found * @return map of Private and its IEDName parameter */ @@ -598,12 +579,14 @@ private static Map createMapIEDNameAndPrivate(SclRootAdapter s .map(TLNode::getPrivate).flatMap(Collection::stream) .filter(tPrivate -> tPrivate.getType().equals(COMPAS_ICDHEADER.getPrivateType()) - && PrivateService.getCompasICDHeader(tPrivate).isPresent() && PrivateService.getCompasICDHeader(tPrivate).get().getIEDName() != null) - .collect(Collectors.toMap(tPrivate -> PrivateService.getCompasICDHeader(tPrivate).get().getIEDName(), Function.identity())); + && PrivateService.extractCompasICDHeader(tPrivate).isPresent() + && PrivateService.extractCompasICDHeader(tPrivate).get().getIEDName() != null) + .collect(Collectors.toMap(tPrivate -> PrivateService.extractCompasICDHeader(tPrivate).get().getIEDName(), Function.identity())); } /** * Sorts in map of ICD_SYSTEM_VERSION_UUID and related Private coupled with all corresponding STD for all given STD + * * @param stds list of STD to short * @return map of ICD_SYSTEM_VERSION_UUID attribute in IED/Private:COMPAS-ICDHeader and related Private coupled with * all corresponding STD @@ -611,7 +594,7 @@ private static Map createMapIEDNameAndPrivate(SclRootAdapter s private static Map>> createMapICDSystemVersionUuidAndSTDFile(Set stds) { Map>> stringSCLMap = new HashMap<>(); stds.forEach(std -> std.getIED().forEach(ied -> ied.getPrivate().forEach(tp -> - PrivateService.getCompasICDHeader(tp).map(TCompasICDHeader::getICDSystemVersionUUID).ifPresent(icdSysVer -> { + PrivateService.extractCompasICDHeader(tp).map(TCompasICDHeader::getICDSystemVersionUUID).ifPresent(icdSysVer -> { Pair> pair = stringSCLMap.get(icdSysVer); List list = pair != null ? pair.getRight() : new ArrayList<>(); list.add(std); @@ -623,16 +606,17 @@ private static Map>> createMapICDSystemVersionU /** * Compares if two Private:COMPAS-ICDHeader have all attributes equal except IEDNane, BayLabel and IEDinstance + * * @param iedPrivate Private of IED from STD to compare * @param scdPrivate Private of LNode fro SCD to compare * @return Boolean value of check result * @throws ScdException throws when Private is not COMPAS_ICDHEADER one */ private static boolean comparePrivateCompasICDHeaders(TPrivate iedPrivate, TPrivate scdPrivate) throws ScdException { - TCompasICDHeader iedCompasICDHeader = PrivateService.getCompasICDHeader(iedPrivate).orElseThrow( - () -> new ScdException(COMPAS_ICDHEADER + "not found in IED Private ")); - TCompasICDHeader scdCompasICDHeader = PrivateService.getCompasICDHeader(scdPrivate).orElseThrow( - () -> new ScdException(COMPAS_ICDHEADER + "not found in LNode Private ")); + TCompasICDHeader iedCompasICDHeader = PrivateService.extractCompasICDHeader(iedPrivate) + .orElseThrow(() -> new ScdException(COMPAS_ICDHEADER + "not found in IED Private ")); + TCompasICDHeader scdCompasICDHeader = PrivateService.extractCompasICDHeader(scdPrivate) + .orElseThrow(() -> new ScdException(COMPAS_ICDHEADER + "not found in LNode Private ")); return iedCompasICDHeader.getIEDType().equals(scdCompasICDHeader.getIEDType()) && iedCompasICDHeader.getICDSystemVersionUUID().equals(scdCompasICDHeader.getICDSystemVersionUUID()) && iedCompasICDHeader.getVendorName().equals(scdCompasICDHeader.getVendorName()) @@ -647,25 +631,27 @@ private static boolean comparePrivateCompasICDHeaders(TPrivate iedPrivate, TPriv /** * Copy Private COMPAS_ICDHEADER from LNode of SCD into Private COMPAS_ICDHEADER from IED of STD - * @param stdPrivate Private of IED from STD in which to copy new data + * + * @param stdPrivate Private of IED from STD in which to copy new data * @param lNodePrivate Private of IED from STD from which new data are taken * @throws ScdException throws when Private is not COMPAS_ICDHEADER one */ private static void copyCompasICDHeaderFromLNodePrivateIntoSTDPrivate(TPrivate stdPrivate, TPrivate lNodePrivate) throws ScdException { - TCompasICDHeader lNodeCompasICDHeader = PrivateService.getCompasICDHeader(lNodePrivate).orElseThrow( - () -> new ScdException(COMPAS_ICDHEADER + " not found in LNode Private ")); + TCompasICDHeader lNodeCompasICDHeader = PrivateService.extractCompasICDHeader(lNodePrivate) + .orElseThrow(() -> new ScdException(COMPAS_ICDHEADER + " not found in LNode Private ")); stdPrivate.getContent().clear(); stdPrivate.getContent().add(objectFactory.createICDHeader(lNodeCompasICDHeader)); } /** * Removes all ControlBlocks and DataSets for all LNs in SCL + * * @param scl SCL file for which ControlBlocks and DataSets should be deleted */ public static void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final SCL scl) { SclRootAdapter sclRootAdapter = new SclRootAdapter(scl); - List lDeviceAdapters = sclRootAdapter.getIEDAdapters().stream() - .map(IEDAdapter::getLDeviceAdapters).flatMap(List::stream).collect(Collectors.toList()); + List lDeviceAdapters = sclRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters).collect(Collectors.toList()); // LN0 lDeviceAdapters.stream() @@ -681,8 +667,9 @@ 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 */ @@ -690,18 +677,15 @@ public static SclReport updateLDeviceStatus(SCL scd) { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); SubstationAdapter substationAdapter = sclRootAdapter.getSubstationAdapter(); final List> iedNameLdInstList = substationAdapter.getIedAndLDeviceNamesForLN0FromLNode(); - List errors = sclRootAdapter.getIEDAdapters().stream() - .map(IEDAdapter::getLDeviceAdapters) - .flatMap(Collection::stream) + List errors = sclRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters) .map(LDeviceAdapter::getLN0Adapter) - .map(ln0Adapter -> ln0Adapter.checkAndUpdateLDeviceStatus(iedNameLdInstList)) - .reduce(new ArrayList<>(),(sclReportErrors, partialSclReportErrors) -> { - sclReportErrors.addAll(partialSclReportErrors); - return sclReportErrors; - }); + .map(ln0Adapter -> ln0Adapter.updateLDeviceStatus(iedNameLdInstList)) + .flatMap(Optional::stream) + .collect(Collectors.toList()); SclReport sclReport = new SclReport(); - sclReport.getErrorDescriptionList().addAll(errors); + sclReport.getSclReportItems().addAll(errors); sclReport.setSclRootAdapter(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 8316d957a..ab7cd032e 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 @@ -5,7 +5,6 @@ package org.lfenergy.compas.sct.commons.scl; import lombok.NonNull; -import lombok.extern.slf4j.Slf4j; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TBay; import org.lfenergy.compas.scl2007b4.model.TSubstation; @@ -31,7 +30,6 @@ * @see org.lfenergy.compas.sct.commons.scl.sstation.LNodeAdapter * @see org.lfenergy.compas.sct.commons.scl.PrivateService */ -@Slf4j public final class SubstationService { /** 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 67428e237..0d4f4c91a 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 @@ -5,7 +5,6 @@ package org.lfenergy.compas.sct.commons.scl.dtt; import lombok.Getter; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.lfenergy.compas.scl2007b4.model.TBDA; import org.lfenergy.compas.scl2007b4.model.TDAType; @@ -52,7 +51,6 @@ * * */ -@Slf4j public class DATypeAdapter extends AbstractDataTypeAdapter{ /** 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 a2e675e29..c2afb9ef7 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 @@ -4,7 +4,6 @@ package org.lfenergy.compas.sct.commons.scl.dtt; -import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.tuple.Pair; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.dto.DaTypeName; @@ -52,7 +51,6 @@ * * */ -@Slf4j public class DOTypeAdapter extends AbstractDataTypeAdapter { /** 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 1138fa98e..09dc91098 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 @@ -67,6 +67,7 @@ * LDName = "name" attribute of IEDName element + "inst" attribute of LDevice element * LNName = "prefix" + "lnClass" + "lnInst" * + * * @see org.lfenergy.compas.scl2007b4.model.TAnyLN */ @Getter @@ -76,32 +77,37 @@ public abstract class AbstractLNAdapter extends SclElementAdap /** * Constructor + * * @param parentAdapter Parent container reference - * @param currentElem Current reference + * @param currentElem Current reference */ protected AbstractLNAdapter(LDeviceAdapter parentAdapter, T currentElem) { super(parentAdapter, currentElem); } - public static LNAdapterBuilder builder(){ + + public static LNAdapterBuilder builder() { return new LNAdapterBuilder(); } protected abstract Class getElementClassType(); + public abstract String getLNClass() ; + public abstract String getLNInst(); + public abstract String getPrefix(); /** * Returns sets of enum value for given ResumedDataTemplate object + * * @param enumType enum Type * @return Enum value list */ public Set getEnumValues(String enumType) { - Optional enumTypeAdapter = parentAdapter - .getParentAdapter().getParentAdapter().getDataTypeTemplateAdapter() + Optional enumTypeAdapter = getDataTypeTemplateAdapter() .getEnumTypeAdapterById(enumType); - if(enumTypeAdapter.isEmpty()){ + if (enumTypeAdapter.isEmpty()) { return Collections.emptySet(); } return enumTypeAdapter.get().getCurrentElem().getEnumVal() @@ -111,23 +117,24 @@ public Set getEnumValues(String enumType) { /** * Add given ControlBlock to LNode + * * @param controlBlock ControlBlock to add * @throws ScdException throws when the ControlBlock type is unknown */ protected void addControlBlock(ControlBlock controlBlock) throws ScdException { - switch (controlBlock.getServiceType() ) { + switch (controlBlock.getServiceType()) { case REPORT: currentElem.getReportControl().add(controlBlock.createControlBlock()); break; case GOOSE: - if(isLN0()) { - ((LN0)currentElem).getGSEControl().add(controlBlock.createControlBlock()); + if (isLN0()) { + ((LN0) currentElem).getGSEControl().add(controlBlock.createControlBlock()); } break; case SMV: - if(isLN0()) { - ((LN0)currentElem).getSampledValueControl().add(controlBlock.createControlBlock()); + if (isLN0()) { + ((LN0) currentElem).getSampledValueControl().add(controlBlock.createControlBlock()); } break; default: @@ -136,46 +143,48 @@ protected void addControlBlock(ControlBlock controlBlock) throws ScdException } } - public Optional findDataSetByRef(String dataSetRef) { + public Optional findDataSetByRef(String dataSetRef) { return currentElem.getDataSet() .stream() - .filter(tDataSet -> Objects.equals(tDataSet.getName(),dataSetRef)) + .filter(tDataSet -> Objects.equals(tDataSet.getName(), dataSetRef)) .findFirst(); } public DOIAdapter getDOIAdapterByName(String doiName) throws ScdException { - String iedName = parentAdapter.getParentAdapter().getName(); + String iedName = getCurrentIed().getName(); String ldInst = parentAdapter.getInst(); return currentElem.getDOI() .stream() .filter(tdoi -> tdoi.getName().equals(doiName)) .findFirst() - .map(tdoi -> new DOIAdapter(this,tdoi)) + .map(tdoi -> new DOIAdapter(this, tdoi)) .orElseThrow( () -> new ScdException( - String.format( "Unknown DOI(%s) in %s%s/%s%s%s", + String.format("Unknown DOI(%s) in %s%s/%s%s%s", doiName, iedName, ldInst, getPrefix(), getLNClass(), getLNInst() ) ) ); } + public List getDOIAdapters() { return currentElem.getDOI() .stream() - .map(tdoi -> new DOIAdapter(this,tdoi)) + .map(tdoi -> new DOIAdapter(this, tdoi)) .collect(Collectors.toList()); } - boolean isLN0(){ + boolean isLN0() { return getElementClassType() == LN0.class; } - public String getLnType(){ + public String getLnType() { return currentElem.getLnType(); } /** * Gets all ExtRefs + * * @return list of LNode ExtRefs elements */ public List getExtRefs() { @@ -184,11 +193,12 @@ public List getExtRefs() { /** * Gets all ExtRefs matches specified ExtRef info + * * @param filter ExtRef filter value * @return list of TExtRef */ public List getExtRefs(ExtRefSignalInfo filter) { - if(!hasInputs()){ + if (!hasInputs()) { return new ArrayList<>(); } @@ -199,20 +209,25 @@ public List getExtRefs(ExtRefSignalInfo filter) { .stream() .filter(tExtRef -> ((filter.getDesc() == null && tExtRef.getDesc().isEmpty()) - || Objects.equals(filter.getDesc(),tExtRef.getDesc()) ) && - Objects.equals(filter.getPDO(),tExtRef.getPDO()) && - Objects.equals(filter.getPDA(),tExtRef.getPDA()) && - Objects.equals(filter.getIntAddr(),tExtRef.getIntAddr()) && - Objects.equals(filter.getPServT(),tExtRef.getPServT())) + || Objects.equals(filter.getDesc(), tExtRef.getDesc())) && + Objects.equals(filter.getPDO(), tExtRef.getPDO()) && + Objects.equals(filter.getPDA(), tExtRef.getPDA()) && + Objects.equals(filter.getIntAddr(), tExtRef.getIntAddr()) && + Objects.equals(filter.getPServT(), tExtRef.getPServT())) .collect(Collectors.toList()); } + /** + * Check whether the LN has an Inputs node + * @return true if the LN has an Inputs node + */ public boolean hasInputs() { - return currentElem.getInputs() != null; + return currentElem.isSetInputs(); } /** * Gets all ExtRefs matches specified ExtRef info without PDA attribute + * * @param signalInfo ExtRef filter value * @return list of TExtRef */ @@ -224,12 +239,12 @@ public List getExtRefsBySignalInfo(ExtRefSignalInfo signalInfo) { if (signalInfo == null) { return currentElem.getInputs().getExtRef(); } - if(!signalInfo.isValid()){ + if (!signalInfo.isValid()) { throw new IllegalArgumentException("Invalid or missing attributes in ExtRef signal info"); } return currentElem.getInputs().getExtRef() .stream() - .filter(tExtRef -> Objects.equals(signalInfo.getDesc(), tExtRef.getDesc()) && + .filter(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()) @@ -239,27 +254,28 @@ public List getExtRefsBySignalInfo(ExtRefSignalInfo signalInfo) { /** * Update LNode ExtRefs data with ExtRefInfo data + * * @param extRefInfo contains new data for LNode ExtREf update * @throws ScdException throws when mandatory data are missing */ public void updateExtRefBinders(ExtRefInfo extRefInfo) throws ScdException { - if(extRefInfo.getBindingInfo() == null || !extRefInfo.getBindingInfo().isValid()){ - throw new ScdException("ExtRef mandatory binding data are missing"); + if (extRefInfo.getBindingInfo() == null || !extRefInfo.getBindingInfo().isValid()) { + throw new ScdException("ExtRef mandatory binding data are missing"); } String iedName = extRefInfo.getHolderIEDName(); String ldInst = extRefInfo.getHolderLDInst(); ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); List tExtRefs = this.getExtRefs(signalInfo); - if(tExtRefs.isEmpty()){ + if (tExtRefs.isEmpty()) { String msg = String.format("Unknown ExtRef [pDO(%s),intAddr(%s)] in %s/%s.%s", - signalInfo.getPDO(), signalInfo.getIntAddr(), iedName, ldInst,getLNClass()); + signalInfo.getPDO(), signalInfo.getIntAddr(), iedName, ldInst, getLNClass()); throw new ScdException(msg); } - if(tExtRefs.size() != 1){ + if (tExtRefs.size() != 1) { log.warn("More the one desc for ExtRef [pDO({}),intAddr({})] in {}{}/{}", - signalInfo.getPDO(), signalInfo.getIntAddr(), iedName, ldInst,getLNClass()); + signalInfo.getPDO(), signalInfo.getIntAddr(), iedName, ldInst, getLNClass()); } TExtRef extRef = tExtRefs.get(0); // update ExtRef with binding info @@ -268,31 +284,32 @@ public void updateExtRefBinders(ExtRefInfo extRefInfo) throws ScdException { /** * Updates ExtRef with data from ExtRefInfo - * @param extRef ExtRef to update + * + * @param extRef ExtRef to update * @param extRefInfo contains new data for LNode ExtREf update */ protected void updateExtRefBindingInfo(TExtRef extRef, ExtRefInfo extRefInfo) { //update binding info ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo(); boolean isSrcReset = false; - if(bindingInfo != null && bindingInfo.isValid()){ + if (bindingInfo != null && bindingInfo.isValid()) { extRef.setIedName(bindingInfo.getIedName()); extRef.setLdInst(bindingInfo.getLdInst()); extRef.setLnInst(bindingInfo.getLnInst()); extRef.getLnClass().clear(); extRef.getLnClass().add(bindingInfo.getLnClass()); - if(bindingInfo.getServiceType() == null && extRefInfo.getSignalInfo() != null){ + if (bindingInfo.getServiceType() == null && extRefInfo.getSignalInfo() != null) { bindingInfo.setServiceType(extRefInfo.getSignalInfo().getPServT()); } extRef.setServiceType(bindingInfo.getServiceType()); extRef.setDaName(null); - if(bindingInfo.getDaName() != null && bindingInfo.getDaName().isDefined()) { + if (bindingInfo.getDaName() != null && bindingInfo.getDaName().isDefined()) { extRef.setDaName(bindingInfo.getDaName().toString()); } extRef.setDoName(null); - if(bindingInfo.getDoName() != null && bindingInfo.getDoName().isDefined()) { + if (bindingInfo.getDoName() != null && bindingInfo.getDoName().isDefined()) { extRef.setDoName(bindingInfo.getDoName().toString()); } @@ -303,9 +320,9 @@ protected void updateExtRefBindingInfo(TExtRef extRef, ExtRefInfo extRefInfo) { } // ExtRefSourceInfo sourceInfo = extRefInfo.getSourceInfo(); - if(sourceInfo != null && isSrcReset){ + if (sourceInfo != null && isSrcReset) { extRef.setSrcLNInst(sourceInfo.getSrcLNInst()); - if(sourceInfo.getSrcLNClass() != null) { + if (sourceInfo.getSrcLNClass() != null) { extRef.getSrcLNClass().add(sourceInfo.getSrcLNClass()); } extRef.setSrcLDInst(sourceInfo.getSrcLDInst()); @@ -316,17 +333,35 @@ protected void updateExtRefBindingInfo(TExtRef extRef, ExtRefInfo extRefInfo) { /** * Gets Control Blocks of LN specified in extRefInfo + * * @param extRefInfo ExtRef signal data for which Control Blocks should be found * @return list of ControlBlock object as ControlBlocks of LNode */ public List> getControlSetByExtRefInfo(ExtRefInfo extRefInfo) { List tDataSets = this.getDataSet(extRefInfo); + return getControlBlocks(tDataSets, extRefInfo.getBindingInfo().getServiceType()); + } + public List> getControlSet(ExtRefInfo extRefInfo) { + List tDataSets = this.getDataSetMatchingExtRefInfo(extRefInfo); return getControlBlocks(tDataSets,extRefInfo.getBindingInfo().getServiceType()); } + + /** + * Gets Control Blocks matching FCDA compatible with specified in extRefInfo + * + * @param extRefInfo ExtRef signal data for which Control Blocks should be found (contain binding info to match with FCDA) + * @return list of ControlBlock object as ControlBlocks of LNode matching FCDA and ExtRef + */ + public List> getControlBlocksForMatchingFCDA(@NonNull ExtRefInfo 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 - * @param tDataSets Data Sets for which Control Blocks are needed + * + * @param tDataSets Data Sets for which Control Blocks are needed * @param serviceType Service Type of Control Blocks needed * @return list of ControlBlock objects */ @@ -336,13 +371,13 @@ protected List> getControlBlocks(List tDataSets, TServ LNodeMetaData metaData = LNodeMetaData.from(this); - for(TDataSet tDataSet : tDataSets){ - if(isLN0() && (serviceType == null || serviceType == TServiceType.GOOSE)) { - tControls = this.lookUpControlBlocksByDataSetRef(tDataSet.getName(),TGSEControl.class); + for (TDataSet tDataSet : tDataSets) { + if (isLN0() && (serviceType == null || serviceType == TServiceType.GOOSE)) { + tControls = this.lookUpControlBlocksByDataSetRef(tDataSet.getName(), TGSEControl.class); controlBlocks.addAll( tControls.stream() .map(tgseControl -> { - var g = new GooseControlBlock((TGSEControl)tgseControl); + var g = new GooseControlBlock((TGSEControl) tgseControl); g.setMetaData(metaData); return g; }) @@ -350,9 +385,9 @@ protected List> getControlBlocks(List tDataSets, TServ ); } - if(isLN0() && (serviceType == null || serviceType == TServiceType.SMV)) { + if (isLN0() && (serviceType == null || serviceType == TServiceType.SMV)) { - tControls = this.lookUpControlBlocksByDataSetRef(tDataSet.getName(),TSampledValueControl.class); + tControls = this.lookUpControlBlocksByDataSetRef(tDataSet.getName(), TSampledValueControl.class); controlBlocks.addAll( tControls.stream() .map(sampledValueControl -> { @@ -364,8 +399,8 @@ protected List> getControlBlocks(List tDataSets, TServ ); } - if(serviceType == null || serviceType == TServiceType.REPORT) { - tControls = this.lookUpControlBlocksByDataSetRef(tDataSet.getName(),TReportControl.class); + if (serviceType == null || serviceType == TServiceType.REPORT) { + tControls = this.lookUpControlBlocksByDataSetRef(tDataSet.getName(), TReportControl.class); controlBlocks.addAll( tControls.stream() .map(reportControl -> { @@ -382,18 +417,19 @@ protected List> getControlBlocks(List tDataSets, TServ /** * Gets Control Blocks for specified Data Set reference + * * @param dataSetRef Data Set for which Control Blocks are needed - * @param cls class type of Control Block (GOOSE, SMV and REPORT) + * @param cls class type of Control Block (GOOSE, SMV and REPORT) + * @param inference type * @return List of Control Blocks corresponding to cls - * @param inference type */ - protected List lookUpControlBlocksByDataSetRef(@NonNull String dataSetRef, Class cls){ + protected List lookUpControlBlocksByDataSetRef(@NonNull String dataSetRef, Class cls) { List ls = new ArrayList<>(); if (TGSEControl.class.equals(cls) && isLN0()) { ls = ((LN0) currentElem).getGSEControl(); - } else if(TSampledValueControl.class.equals(cls) && isLN0()){ - ls = ((LN0) currentElem).getSampledValueControl(); - } else if(TReportControl.class.equals(cls)){ + } else if (TSampledValueControl.class.equals(cls) && isLN0()) { + ls = ((LN0) currentElem).getSampledValueControl(); + } else if (TReportControl.class.equals(cls)) { ls = currentElem.getReportControl(); } @@ -405,39 +441,42 @@ protected List lookUpControlBlocksByDataSetRef(@NonNull /** * Checks if FCDA is null + * * @param tfcda FCDA to check * @return Boolean value of check result */ - public static boolean isNull(TFCDA tfcda){ + //TODO check method should be checked, why nullability is checked only for this parameters + public static boolean isFCDANull(TFCDA tfcda){ return Objects.isNull(tfcda.getLdInst()) && tfcda.getLnClass().isEmpty() && - Objects.isNull(tfcda.getFc()) ; + Objects.isNull(tfcda.getFc()); } /** * Checks if specified Control Block is present in LNode + * * @param controlBlock Control Block to check * @return Boolean value of check result */ public boolean hasControlBlock(ControlBlock controlBlock) { - switch (controlBlock.getServiceType()){ + switch (controlBlock.getServiceType()) { case REPORT: return currentElem.getReportControl().stream() .anyMatch(control -> control.getName().equals(controlBlock.getName())); case GOOSE: - return isLN0() && ((LN0)currentElem).getGSEControl().stream() + return isLN0() && ((LN0) currentElem).getGSEControl().stream() .anyMatch(control -> control.getName().equals(controlBlock.getName())); case SMV: - return isLN0() && ((LN0)currentElem).getSampledValueControl().stream() + return isLN0() && ((LN0) currentElem).getSampledValueControl().stream() .anyMatch(reportControl -> reportControl.getName().equals(controlBlock.getName())); default: return false; } } - public List getDataSet(ExtRefInfo filter){ + public List getDataSet(ExtRefInfo filter) { if (filter == null || filter.getSignalInfo() == null || filter.getBindingInfo() == null) { return currentElem.getDataSet(); } @@ -451,8 +490,24 @@ public List getDataSet(ExtRefInfo filter){ .collect(Collectors.toList()); } + /** + * retrieves all DataSets for which at least one FCDA mathches with data given in ExtRefInfo for external binding + * @param filter contains data for external binding which should match with FCDAs values + * @return list of Data for which at least one FCDA mathches with filter datas + */ + public List getDataSetMatchingExtRefInfo(ExtRefInfo filter){ + return currentElem.getDataSet() + .stream() + .filter(tDataSet -> tDataSet.getFCDA() + .stream() + .anyMatch(filter::checkMatchingFCDA) + ) + .collect(Collectors.toList()); + } + /** * Updates ExtRef source binding data's based on given data in extRefInfo + * * @param extRefInfo new data for ExtRef source binding data * @return TExtRef object as update ExtRef with new source binding data * @throws ScdException throws when mandatory data of ExtRef are missing @@ -462,11 +517,12 @@ public TExtRef updateExtRefSource(ExtRefInfo extRefInfo) throws ScdException { ExtRefSourceInfo sourceInfo = extRefInfo.getSourceInfo(); ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo(); - if(signalInfo == null || bindingInfo == null || sourceInfo == null){ + if (signalInfo == null || bindingInfo == null || sourceInfo == null) { throw new IllegalArgumentException("ExtRef information (signal, binding, source) are missing"); } + TExtRef extRef = checkExtRefInfoCoherence(extRefInfo); - updateExtRefBindingInfo(extRef,extRefInfo); + updateExtRefBindingInfo(extRef, extRefInfo); return extRef; } @@ -476,22 +532,22 @@ public TExtRef updateExtRefSource(ExtRefInfo extRefInfo) throws ScdException { * This method look up the TExtRef that matches the signal info in this LNode. Then verify the coherence * between the ExtRef's binding info and the given binding info. If the ExtRef info contains a source information ( * ControlBlock info),it verifies that the CB and dataset it points to, exists within and existing binder IED. + * * @param extRefInfo ExtRef information (signal, binding and source info) * @return TExtRef that matches the signal info * @throws IllegalArgumentException when no given signal info - * @throws ScdException throws exception if - *
      - *
    • given signal info or it doesn't match any TExtRef in this LNode
    • - *
    • the given binding info doesn't match the found TExtRef's binding info.
    • - *
    • the given binding info doesn't refer to an exiting IED, LDevice and LNode in the SCL
    • - *
    • given source info references unknown control block
    • - *
    + * @throws ScdException throws exception if + *
      + *
    • given signal info or it doesn't match any TExtRef in this LNode
    • + *
    • the given binding info doesn't match the found TExtRef's binding info.
    • + *
    • the given binding info doesn't refer to an exiting IED, LDevice and LNode in the SCL
    • + *
    • given source info references unknown control block
    • + *
    */ public TExtRef checkExtRefInfoCoherence(@NonNull ExtRefInfo extRefInfo) throws ScdException { - ExtRefSignalInfo signalInfo = extRefInfo.getSignalInfo(); ExtRefBindingInfo bindingInfo = extRefInfo.getBindingInfo(); - if(signalInfo == null ) { + if (signalInfo == null) { log.error("Coherence checking needs at least a signal info"); throw new IllegalArgumentException("Coherence checking needs at least a signal info"); } @@ -499,20 +555,20 @@ public TExtRef checkExtRefInfoCoherence(@NonNull ExtRefInfo extRefInfo) throws S String holderIedName = extRefInfo.getHolderIEDName(); // parent (IED) of parent (LD) can be used here String holderLdInst = extRefInfo.getHolderLDInst(); // parent (LD) can be use here List extRefs = getExtRefs(signalInfo); - if(extRefs.isEmpty()){ + if (extRefs.isEmpty()) { String msg = String.format("Unknown TExtRef with signal info [pDO(%s),intAddr(%s)] in %s%s/%s%s%s", signalInfo.getPDO(), signalInfo.getIntAddr(), holderIedName, holderLdInst, - getPrefix(),getLNClass(),getLNInst()); + getPrefix(), getLNClass(), getLNInst()); log.error(msg); throw new ScdException(msg); } TExtRef extRef = extRefs.get(0); // to be refined : what's the criteria for ExtRef's uniqueness - if(bindingInfo == null){ + if (bindingInfo == null) { return extRef; } - if(!bindingInfo.isWrappedIn(extRef)){ + if (!bindingInfo.isWrappedIn(extRef)) { String msg = "No relation between binding info and the matched TExtRef"; log.error(msg); throw new ScdException(msg); @@ -523,12 +579,12 @@ public TExtRef checkExtRefInfoCoherence(@NonNull ExtRefInfo extRefInfo) throws S String binderLnClass = bindingInfo.getLnClass(); String binderLnInst = bindingInfo.getLnInst(); String binderLnPrefix = bindingInfo.getPrefix(); + IEDAdapter binderIEDAdapter; - if(!binderIedName.equals( parentAdapter.getParentAdapter().getName())){ // external binding - SclRootAdapter sclRootAdapter = parentAdapter.getParentAdapter().getParentAdapter(); - binderIEDAdapter = sclRootAdapter.getIEDAdapterByName(binderIedName); + if(!binderIedName.equals( getCurrentIed().getName())){ // external binding + binderIEDAdapter = getCurrentScd().getIEDAdapterByName(binderIedName); } else { - binderIEDAdapter = parentAdapter.getParentAdapter(); + binderIEDAdapter = getCurrentIed(); } LDeviceAdapter binderLDAdapter = binderIEDAdapter.getLDeviceAdapterByLdInst(binderLdInst) .orElseThrow( @@ -543,13 +599,14 @@ public TExtRef checkExtRefInfoCoherence(@NonNull ExtRefInfo extRefInfo) throws S .withLnPrefix(binderLnPrefix) .build(); + boolean isCoherent; ExtRefSourceInfo sourceInfo = extRefInfo.getSourceInfo(); - if(sourceInfo == null || sourceInfo.isNull()) { // to be refined : what to do here functionally ? + if (sourceInfo == null || sourceInfo.isNull()) { // to be refined : what to do here functionally ? return extRef; } List> cbs = anLNAdapter.getControlSetByExtRefInfo(extRefInfo); - boolean isCoherent = !cbs.isEmpty() && cbs.stream() + isCoherent = !cbs.isEmpty() && cbs.stream() .anyMatch(controlBlock -> controlBlock.getName().equals(sourceInfo.getSrcCBName())); if(!isCoherent){ String msg = String.format("Unknown control block %s in %s%s/%s%s%s", @@ -562,32 +619,33 @@ public TExtRef checkExtRefInfoCoherence(@NonNull ExtRefInfo extRefInfo) throws S return extRef; } + /** * Returns a list of resumed DataTypeTemplate for DataAttribute (updatable or not) - * @param rDtt reference resumed DataTypeTemplate (used as filter) + * + * @param rDtt reference resumed DataTypeTemplate (used as filter) * @param updatableOnly true to retrieve DataTypeTemplate's related to only updatable DAI, false to retrieve all * @return List of resumed DataTypeTemplate for DataAttribute (updatable or not) * @throws ScdException SCD illegal arguments exception */ public List getDAI(ResumedDataTemplate rDtt, boolean updatableOnly) throws ScdException { String lnType = currentElem.getLnType(); - if(!StringUtils.isBlank(rDtt.getLnType())){ + if (!StringUtils.isBlank(rDtt.getLnType())) { lnType = rDtt.getLnType(); } // get resumedDTT from DataTypeTemplate (it might be overridden in the DAI) - SclRootAdapter sclRootAdapter = parentAdapter.getParentAdapter().getParentAdapter(); - DataTypeTemplateAdapter dttAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); + DataTypeTemplateAdapter dttAdapter = getDataTypeTemplateAdapter(); LNodeTypeAdapter lNodeTypeAdapter = dttAdapter.getLNodeTypeAdapterById(lnType) .orElseThrow( () -> new ScdException( - String.format("Corrupted SCD : lnType missing for LN : %s%s", getLNClass(),getLNInst()) + String.format("Corrupted SCD : lnType missing for LN : %s%s", getLNClass(), getLNInst()) ) ); List resumedDTTs = lNodeTypeAdapter.getResumedDTTs(rDtt); resumedDTTs.forEach(this::overrideAttributesFromDAI); - if (updatableOnly){ + if (updatableOnly) { return resumedDTTs.stream().filter(ResumedDataTemplate::isUpdatable).collect(Collectors.toList()); } else { return resumedDTTs; @@ -596,6 +654,7 @@ public List getDAI(ResumedDataTemplate rDtt, boolean updata /** * Update given ResumedDataTemplate DAI datas from LNode + * * @param rDtt summarized Data Type Template object to update DAI datas */ protected void overrideAttributesFromDAI(final ResumedDataTemplate rDtt) { @@ -611,7 +670,7 @@ protected void overrideAttributesFromDAI(final ResumedDataTemplate rDtt) { } else { rDtt.setValImport(false); log.warn("Inconsistency in the SCD file - DAI {} with fc={} must have a sGroup attribute", - rDtt.getObjRef(getCurrentIED().getName(), parentAdapter.getInst()), rDtt.getDaName().getFc()); + rDtt.getObjRef(getCurrentIed().getName(), parentAdapter.getInst()), rDtt.getDaName().getFc()); } } else if (tdai.isSetValImport()) { rDtt.setValImport(tdai.isValImport()); @@ -621,25 +680,44 @@ protected void overrideAttributesFromDAI(final ResumedDataTemplate rDtt) { /** * Checks if linked IED as parent has Setting Group set + * * @return Boolean value of check result */ private boolean iedHasConfSG() { - IEDAdapter iedAdapter = getCurrentIED(); + IEDAdapter iedAdapter = getCurrentIed(); return iedAdapter.isSettingConfig(this.parentAdapter.getInst()); } /** * Gets linked IED as parent + * * @return IEDAdapter object */ - private IEDAdapter getCurrentIED() { + private IEDAdapter getCurrentIed() { LDeviceAdapter lDeviceAdapter = this.parentAdapter; return lDeviceAdapter.getParentAdapter(); } + /** + * Gets root Scd + * @return SclRootAdapter object + */ + protected SclRootAdapter getCurrentScd() { + return getCurrentIed().getParentAdapter(); + } + + /** + * Gets SCL DataTypeTemplate + * @return DataTypeTemplateAdapter object + */ + public DataTypeTemplateAdapter getDataTypeTemplateAdapter() { + return getCurrentScd().getDataTypeTemplateAdapter(); + } + /** * Checks fro DAI if Setting Group value is set correctly + * * @param tdai DAI for which check is done * @return Boolean value of check result */ @@ -650,14 +728,15 @@ private boolean hasSgGroup(TDAI tdai) { /** * Search for DAI that match the given defined-DO (do.sdo1[.sdo2 ...sdo_n]) and defined-DA (da.bda1[.bda2...bda_n]) * where 'sdo_n' points to a DOType that contains 'da' + * * @param doTypeName defined-DO (do.sdo1[.sdo2 ...sdo_n]) * @param daTypeName defined-DA (da.bda1[.bda2...bda_n]) * @return Optional of DAIAdapter for the matched DAI */ - protected Optional findMatch(DoTypeName doTypeName, DaTypeName daTypeName){ - DAITracker daiTracker = new DAITracker(this,doTypeName,daTypeName); + protected Optional findMatch(DoTypeName doTypeName, DaTypeName daTypeName) { + DAITracker daiTracker = new DAITracker(this, doTypeName, daTypeName); DAITracker.MatchResult matchResult = daiTracker.search(); - if(matchResult != DAITracker.MatchResult.FULL_MATCH){ + if (matchResult != DAITracker.MatchResult.FULL_MATCH) { return Optional.empty(); } return Optional.of(daiTracker.getBdaiOrDaiAdapter()); @@ -667,35 +746,36 @@ protected Optional findMatch(DoTypeName doTypeName, DaTypeName daT * Updates DAI (in LNode section) after checking updatability with summarized Data Type Template given information and LNode * Summarized Data Type Temple and LNode helps to check updatability. rDtt gives DAI which should be found in LNode, * that LNode gives LNodeType localized in DataTypeTemplate section and contains DOType in which the DAI is localized. + * * @param rDtt summarized Data Type Temple containing new DO and DA data's * @throws ScdException when inconsistency are found in th SCL's - * DataTypeTemplate. Which should normally not happens. + * DataTypeTemplate. Which should normally not happens. */ public void updateDAI(@NonNull ResumedDataTemplate rDtt) throws ScdException { - if(!rDtt.isDoNameDefined() || !rDtt.isDaNameDefined()){ + if (!rDtt.isDoNameDefined() || !rDtt.isDaNameDefined()) { throw new ScdException("Cannot update undefined DAI"); } DoTypeName doTypeName = rDtt.getDoName(); DaTypeName daTypeName = rDtt.getDaName(); - DAITracker daiTracker = new DAITracker(this,doTypeName,daTypeName); + DAITracker daiTracker = new DAITracker(this, doTypeName, daTypeName); DAITracker.MatchResult matchResult = daiTracker.search(); AbstractDAIAdapter daiAdapter = null; IDataParentAdapter doiOrSdoiAdapter; - if(matchResult == DAITracker.MatchResult.FULL_MATCH){ + if (matchResult == DAITracker.MatchResult.FULL_MATCH) { // update daiAdapter = (AbstractDAIAdapter) daiTracker.getBdaiOrDaiAdapter(); - if((daiAdapter.isValImport() != null && daiAdapter.isValImport()) || - (daiAdapter.isValImport() == null && rDtt.isUpdatable()) ) { + if ((daiAdapter.isValImport() != null && daiAdapter.isValImport()) || + (daiAdapter.isValImport() == null && rDtt.isUpdatable())) { daiAdapter.update(daTypeName.getDaiValues()); return; - } else{ - throw new ScdException(String.format("DAI (%s -%s) cannot be updated",doTypeName,daTypeName)); + } else { + throw new ScdException(String.format("DAI (%s -%s) cannot be updated", doTypeName, daTypeName)); } } - if(rDtt.isUpdatable()) { + if (rDtt.isUpdatable()) { doiOrSdoiAdapter = daiTracker.getDoiOrSdoiAdapter(); int idx = daiTracker.getIndexDoType(); int doSz = doTypeName.getStructNames().size(); @@ -715,23 +795,23 @@ public void updateDAI(@NonNull ResumedDataTemplate rDtt) throws ScdException { IDataParentAdapter daiOrBdaiAdapter = daiTracker.getDoiOrSdoiAdapter(); idx = daiTracker.getIndexDaType(); int daSz = daTypeName.getStructNames().size(); - if(idx <= -1 ){ + if (idx <= -1) { idx = 0; - } else if(idx == daSz - 1){ + } else if (idx == daSz - 1) { idx = daSz; } - for(int i = idx; i < daSz; ++i){ + for (int i = idx; i < daSz; ++i) { String bdaName = daTypeName.getStructNames().get(i); - if(idx == 0){ + if (idx == 0) { daiOrBdaiAdapter = doiOrSdoiAdapter.addSDOI(daTypeName.getName()); - } else if(i == daSz -1){ + } else if (i == daSz - 1) { daiAdapter = daiOrBdaiAdapter.addDAI(bdaName, rDtt.isUpdatable()); } else { daiOrBdaiAdapter = daiOrBdaiAdapter.addSDOI(bdaName); } } - if(daiAdapter == null){ - daiAdapter = doiOrSdoiAdapter.addDAI(daTypeName.getName(),rDtt.isUpdatable()); + if (daiAdapter == null) { + daiAdapter = doiOrSdoiAdapter.addDAI(daTypeName.getName(), rDtt.isUpdatable()); } daiAdapter.update(daTypeName.getDaiValues()); @@ -740,6 +820,7 @@ public void updateDAI(@NonNull ResumedDataTemplate rDtt) throws ScdException { /** * Adds DO in LNode + * * @param name DOI name * @return added DOIAdapter object */ @@ -748,13 +829,13 @@ protected DOIAdapter addDOI(String name) { tdoi.setName(name); currentElem.getDOI().add(tdoi); - return new DOIAdapter(this,tdoi); + return new DOIAdapter(this, tdoi); } public String getLNodeName() { StringBuilder stringBuilder = new StringBuilder(); - if(TLLN0Enum.LLN_0.value().equals(getLNClass())){ + if (TLLN0Enum.LLN_0.value().equals(getLNClass())) { stringBuilder.append(TLLN0Enum.LLN_0.value()); } else { stringBuilder.append(getPrefix()) @@ -767,13 +848,13 @@ public String getLNodeName() { /** * Checks given reference matches with DataSet or ReportControl or DataTypeTemplate element for calling LNode * in SCL file + * * @param objRef reference to compare with LNode datas * @return Boolean value of check result */ public boolean matches(ObjectReference objRef) { String dataAttribute = objRef.getDataAttributes(); - SclRootAdapter sclRootAdapter = parentAdapter.getParentAdapter().getParentAdapter(); - DataTypeTemplateAdapter dttAdapter = sclRootAdapter.getDataTypeTemplateAdapter(); + DataTypeTemplateAdapter dttAdapter = getDataTypeTemplateAdapter(); LNodeTypeAdapter lNodeTypeAdapter = dttAdapter.getLNodeTypeAdapterById(getLnType()) .orElseThrow( () -> new AssertionError( @@ -792,16 +873,18 @@ public boolean matches(ObjectReference objRef) { /** * Checks if given attibrute corresponds to DataSet or ReportControl in LNode + * * @param dataAttribute attribute to check * @return Boolean value of check result */ - protected boolean matchesDataAttributes(String dataAttribute){ - return currentElem.getDataSet().stream().anyMatch(tDataSet -> tDataSet.getName().equals(dataAttribute)) || + protected boolean matchesDataAttributes(String dataAttribute) { + return currentElem.getDataSet().stream().anyMatch(tDataSet -> tDataSet.getName().equals(dataAttribute)) || currentElem.getReportControl().stream().anyMatch(rptCtl -> rptCtl.getName().equals(dataAttribute)); } /** * Gets Data Set in LNode by its name + * * @param dataSetRef Data Set name * @return optional of DataSetInfo */ @@ -815,6 +898,7 @@ public Optional getDataSetByRef(String dataSetRef) { /** * Adds Data Set to LNode Data Sets + * * @param dataSetInfo data's of Data Set to add */ public void addDataSet(DataSetInfo dataSetInfo) { @@ -827,33 +911,30 @@ public void addDataSet(DataSetInfo dataSetInfo) { } - public DataTypeTemplateAdapter getDataTypeTemplateAdapter() { - return parentAdapter.getParentAdapter().getParentAdapter().getDataTypeTemplateAdapter(); - } - /** * Gets DAI values for specified DA in summaraized Data Type Template + * * @param rDtt summaraized Data Type Template containing DA datas * @return map of Setting Group and it's VAL */ public Map getDAIValues(ResumedDataTemplate rDtt) { - DAITracker daiTracker = new DAITracker(this,rDtt.getDoName(),rDtt.getDaName()); + DAITracker daiTracker = new DAITracker(this, rDtt.getDoName(), rDtt.getDaName()); DAITracker.MatchResult matchResult = daiTracker.search(); - if(matchResult != DAITracker.MatchResult.FULL_MATCH){ + if (matchResult != DAITracker.MatchResult.FULL_MATCH) { return new HashMap<>(); } List tVals; IDataAdapter daiAdapter = daiTracker.getBdaiOrDaiAdapter(); - if(daiAdapter.getClass().equals(SDIAdapter.DAIAdapter.class)){ - tVals = ((RootSDIAdapter.DAIAdapter)daiAdapter).getCurrentElem().getVal(); - } else if(daiAdapter.getClass().equals(RootSDIAdapter.DAIAdapter.class)){ - tVals = ((RootSDIAdapter.DAIAdapter)daiAdapter).getCurrentElem().getVal(); + if (daiAdapter.getClass().equals(SDIAdapter.DAIAdapter.class)) { + tVals = ((RootSDIAdapter.DAIAdapter) daiAdapter).getCurrentElem().getVal(); + } else if (daiAdapter.getClass().equals(RootSDIAdapter.DAIAdapter.class)) { + tVals = ((RootSDIAdapter.DAIAdapter) daiAdapter).getCurrentElem().getVal(); } else { - tVals = ((DOIAdapter.DAIAdapter)daiAdapter).getCurrentElem().getVal(); + tVals = ((DOIAdapter.DAIAdapter) daiAdapter).getCurrentElem().getVal(); } - Map res = new HashMap<>(); - tVals.forEach( tVal -> res.put( + Map res = new HashMap<>(); + tVals.forEach(tVal -> res.put( tVal.isSetSGroup() ? tVal.getSGroup() : 0L, tVal.getValue()) ); @@ -878,9 +959,10 @@ public void removeAllExtRefSourceBindings() { /** * Removes specified ExtRef Source binding data's + * * @param tExtRef ExtRef Source for which binding data's should be removed */ - private void removeExtRefSourceBinding(final TExtRef tExtRef){ + private void removeExtRefSourceBinding(final TExtRef tExtRef) { tExtRef.setSrcCBName(null); tExtRef.setSrcLDInst(null); tExtRef.setSrcPrefix(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 fd84454af..7985aa0bc 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 @@ -5,7 +5,7 @@ package org.lfenergy.compas.sct.commons.scl.ied; import lombok.NonNull; -import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.dto.ControlBlock; import org.lfenergy.compas.sct.commons.dto.DataSetInfo; @@ -17,8 +17,12 @@ import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.util.Utils; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * A representation of the model object @@ -29,7 +33,7 @@ *
      *
    1. Adapter
    2. *
        - *
      • {@link IEDAdapter#getLDeviceAdapters Returns the value of the LDeviceAdapter containment reference list}
      • + *
      • {@link IEDAdapter#streamLDeviceAdapters LDeviceAdapters Returns the value of the LDeviceAdapter containment reference list}
      • *
      • {@link IEDAdapter#getLDeviceAdapterByLdInst Returns the value of the LDeviceAdapter reference object By LDevice Inst}
      • *
      *
    3. Principal functions
    4. @@ -56,7 +60,6 @@ * @see org.lfenergy.compas.scl2007b4.model.TSettingGroups * @see Issue !3 (Add new IEDs) */ -@Slf4j public class IEDAdapter extends SclElementAdapter { /** @@ -114,17 +117,28 @@ public void setIEDName(String iedName) { } /** - * Gets all LDevices linked to current IED - * @return list of LDeviceAdapter + * Gets All LDevice from current IED as LDeviceAdapter + * @return Stream of LDeviceAdapter object */ - public List getLDeviceAdapters(){ - return currentElem.getAccessPoint() - .stream() - .filter(tAccessPoint -> tAccessPoint.getServer() != null) - .map(tAccessPoint -> tAccessPoint.getServer().getLDevice()) - .flatMap(Collection::stream) - .map(tlDevice -> new LDeviceAdapter(this,tlDevice)) - .collect(Collectors.toList()); + public Stream streamLDeviceAdapters() { + return streamLDevices() + .map(tlDevice -> new LDeviceAdapter(this, tlDevice)); + } + + /** + * Gets All LDevice from current IED + * @return Stream of TLDevice object + */ + private Stream streamLDevices() { + if (!currentElem.isSetAccessPoint()){ + return Stream.empty(); + } + return currentElem.getAccessPoint().stream() + .map(TAccessPoint::getServer) + .filter(Objects::nonNull) + .filter(TServer::isSetLDevice) + .map(TServer::getLDevice) + .flatMap(List::stream); } /** @@ -132,15 +146,11 @@ public List getLDeviceAdapters(){ * @param ldInst ldInst value of LDevice to get * @return optional of LDeviceAdapter object */ - public Optional getLDeviceAdapterByLdInst(String ldInst){ - return currentElem.getAccessPoint() - .stream() - .filter(tAccessPoint -> tAccessPoint.getServer() != null) - .map(tAccessPoint -> tAccessPoint.getServer().getLDevice()) - .flatMap(Collection::stream) - .filter(tlDevice -> Objects.equals(ldInst,tlDevice.getInst())) - .map(tlDevice -> new LDeviceAdapter(this,tlDevice)) - .findFirst(); + public Optional getLDeviceAdapterByLdInst(String ldInst) { + return streamLDevices() + .filter(tlDevice -> Utils.equalsOrBothBlank(tlDevice.getInst(), ldInst)) + .findFirst() + .map(tlDevice -> new LDeviceAdapter(this, tlDevice)); } /** @@ -152,22 +162,20 @@ public Optional getLDeviceAdapterByLdInst(String ldInst){ */ public void updateLDeviceNodesType(Map pairOldNewId) throws ScdException { // renaming ldName - for(LDeviceAdapter lDeviceAdapter : getLDeviceAdapters()) { + streamLDeviceAdapters().forEach(lDeviceAdapter -> { lDeviceAdapter.updateLDName(); String lnType = lDeviceAdapter.getCurrentElem().getLN0().getLnType(); - if(pairOldNewId.containsKey(lnType)){ + if (pairOldNewId.containsKey(lnType)) { lDeviceAdapter.getCurrentElem().getLN0().setLnType(pairOldNewId.get(lnType)); } lDeviceAdapter.getCurrentElem() - .getLN() - .stream() - .forEach(tln -> { - if(pairOldNewId.containsKey(tln.getLnType())) { - tln.setLnType(pairOldNewId.get(tln.getLnType())); - } - }); - - } + .getLN() + .forEach(tln -> { + if (pairOldNewId.containsKey(tln.getLnType())) { + tln.setLnType(pairOldNewId.get(tln.getLnType())); + } + }); + }); } /** @@ -193,20 +201,16 @@ public String getName(){ * @return Boolean value of check result */ public boolean matches(ObjectReference objRef){ - if(!objRef.getLdName().startsWith(getName())) { + if (StringUtils.isBlank(getName()) + || !objRef.getLdName().startsWith(getName())) { return false; } - Optional opLD = currentElem.getAccessPoint() - .stream() - .filter(tAccessPoint -> tAccessPoint.getServer() != null) - .map(tAccessPoint -> tAccessPoint.getServer().getLDevice()) - .flatMap(Collection::stream) - .filter(tlDevice -> objRef.getLdName().equals(getName() + tlDevice.getInst())) - .findFirst(); + String ldInst = objRef.getLdName().substring(getName().length()); + Optional opLD = getLDeviceAdapterByLdInst(ldInst); if(opLD.isEmpty()) { return false; } - LDeviceAdapter lDeviceAdapter = new LDeviceAdapter(this,opLD.get()); + LDeviceAdapter lDeviceAdapter = opLD.get(); if(TLLN0Enum.LLN_0.value().equals(objRef.getLNodeName())) { return lDeviceAdapter.getLN0Adapter().matches(objRef); } @@ -238,12 +242,9 @@ public List getExtRefBinders(@NonNull ExtRefSignalInfo signal if(!signalInfo.isValid()){ throw new ScdException("Invalid ExtRef signal (pDO,pDA or intAddr))"); } - List potentialBinders = new ArrayList<>(); - List lDeviceAdapters = getLDeviceAdapters(); - for (LDeviceAdapter lDeviceAdapter : lDeviceAdapters) { - potentialBinders.addAll(lDeviceAdapter.getExtRefBinders(signalInfo)); - } - return potentialBinders; + return streamLDeviceAdapters() + .map(lDeviceAdapter -> lDeviceAdapter.getExtRefBinders(signalInfo)).flatMap(List::stream) + .collect(Collectors.toList()); } /** @@ -350,7 +351,7 @@ public ControlBlock createControlBlock(ControlBlock lnAdapter = AbstractLNAdapter.builder() .withLDeviceAdapter(lDeviceAdapter) .withLnClass(controlBlock.getHolderLnClass()) 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 new file mode 100644 index 000000000..8cb5f1a43 --- /dev/null +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapter.java @@ -0,0 +1,244 @@ +// SPDX-FileCopyrightText: 2021 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.scl.ied; + + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +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.ResumedDataTemplate; +import org.lfenergy.compas.sct.commons.dto.SclReportItem; +import org.lfenergy.compas.sct.commons.scl.PrivateService; +import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; +import org.lfenergy.compas.sct.commons.util.Utils; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.lfenergy.compas.sct.commons.util.LDeviceStatus.OFF; +import static org.lfenergy.compas.sct.commons.util.LDeviceStatus.ON; + +/** + * A representation of the model object + * {@link InputsAdapter InputsAdapter}. + * + * @See TInputs + * @See TExtRef + * @see LN0Adapter + * @see AbstractLNAdapter + */ +@Slf4j +public class InputsAdapter extends SclElementAdapter { + + public static final String MESSAGE_NO_MATCHING_COMPAS_FLOW = "The signal ExtRef has no matching compas:Flow Private"; + public static final String MESSAGE_TOO_MANY_MATCHING_COMPAS_FLOWS = "The signal ExtRef has more than one matching compas:Flow Private"; + + /** + * Constructor + * + * @param parentAdapter Parent container reference + * @param tInputs Current reference + */ + public InputsAdapter(LN0Adapter parentAdapter, TInputs tInputs) { + super(parentAdapter, tInputs); + } + + /** + * Check if current element is a child of the parent element + * + * @return true if the currentElem is part of the parentAdapter children + */ + @Override + protected boolean amChildElementRef() { + return currentElem == parentAdapter.getCurrentElem().getInputs(); + } + + @Override + protected String elementXPath() { + return "Inputs"; + } + + /** + * Update iedName of all ExtRefs in this "Inputs" element. + * + * @return list of encountered errors + */ + public List updateAllExtRefIedNames(Map icdSystemVersionToIed) { + Optional optionalLDeviceStatus = getLDeviceAdapter().getLDeviceStatus(); + if (optionalLDeviceStatus.isEmpty()) { + return List.of(getLDeviceAdapter().buildFatalReportItem("The LDevice status is undefined")); + } + String lDeviceStatus = optionalLDeviceStatus.get(); + switch (lDeviceStatus) { + case ON: + List compasFlows = PrivateService.extractCompasPrivates(currentElem, TCompasFlow.class); + return getExtRefs().stream() + .filter(tExtRef -> StringUtils.isNotBlank(tExtRef.getIedName()) && StringUtils.isNotBlank(tExtRef.getDesc())) + .map(extRef -> + updateExtRefIedName(extRef, compasFlows, icdSystemVersionToIed.get(extRef.getIedName()))) + .flatMap(Optional::stream) + .collect(Collectors.toList()); + case OFF: + getExtRefs().forEach(this::clearBinding); + return Collections.emptyList(); + default: + return List.of(getLDeviceAdapter() + .buildFatalReportItem("The LDevice status is neither \"on\" nor \"off\"")); + } + } + + /** + * Find matching CompasFlow private and set ExtRef iedName accordingly + * + * @param extRef extRef whose iedName will be updated + * @param allCompasFlows list of all CompasFlow private in this Inputs + * @return Error if ExtRef could not be updated + */ + private Optional updateExtRefIedName(TExtRef extRef, final List allCompasFlows, IEDAdapter sourceIed) { + List matchingCompasFlows = getMatchingCompasFlows(extRef, allCompasFlows); + if (!singleMatch(matchingCompasFlows)) { + return fatalReportItem(extRef, + matchingCompasFlows.isEmpty() ? MESSAGE_NO_MATCHING_COMPAS_FLOW : MESSAGE_TOO_MANY_MATCHING_COMPAS_FLOWS); + } + TCompasFlow compasFlow = matchingCompasFlows.get(0); + if (compasFlow.getFlowStatus() == TCompasFlowStatus.INACTIVE) { + clearBinding(extRef); + return Optional.empty(); + } + Optional sourceValidationError = validateExtRefSource(extRef, sourceIed); + if (sourceValidationError.isPresent()) { + clearBinding(extRef); + return sourceValidationError; + } + String sourceIedName = PrivateService.extractCompasPrivate(sourceIed.getCurrentElem(), TCompasICDHeader.class) + .map(TCompasICDHeader::getIEDName).orElse(""); + extRef.setIedName(sourceIedName); + compasFlow.setExtRefiedName(sourceIedName); + log.debug(String.format("extRef.desc=%s, iedName=%s%n", extRef.getDesc(), sourceIedName)); + return Optional.empty(); + } + + /** + * List all ExtRefs in this Inputs + * + * @return list of ExtRefs. List is modifiable. + */ + private List getExtRefs() { + if (!currentElem.isSetExtRef()) { + return Collections.emptyList(); + } + return currentElem.getExtRef(); + } + + private Optional validateExtRefSource(TExtRef extRef, IEDAdapter sourceIed) { + if (sourceIed == null) { + return warningReportItem(extRef, "The signal ExtRef iedName does not match any " + + "IED/Private/compas:ICDHeader@ICDSystemVersionUUID"); + } + Optional optionalSourceLDevice = sourceIed.getLDeviceAdapterByLdInst(extRef.getLdInst()); + if (optionalSourceLDevice.isEmpty()) { + return warningReportItem(extRef, String.format("The signal ExtRef ExtRefldinst does not match any " + + "LDevice with same inst attribute in source IED %s", sourceIed.getXPath())); + } + LDeviceAdapter sourceLDevice = optionalSourceLDevice.get(); + if (!hasMatchingLN(extRef, sourceLDevice)) { + 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()) { + 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(); + } + + private boolean hasMatchingLN(TExtRef extRef, LDeviceAdapter lDeviceAdapter) { + String extRefLnClass = extRef.getLnClass().stream().findFirst().orElse(""); + ResumedDataTemplate filter = ResumedDataTemplate.builder() + .lnClass(extRefLnClass) + .prefix(extRef.getPrefix()) + .lnInst(extRef.getLnInst()) + .doName(new DoTypeName(extRef.getDoName())) + .daName(new DaTypeName(extRef.getDaName())) + .build(); + return !lDeviceAdapter.getDAI(filter, false).isEmpty(); + } + + private boolean singleMatch(List matchingCompasFlows) { + return matchingCompasFlows.size() == 1; + } + + private void clearBinding(TExtRef extRef) { + extRef.setIedName(null); + extRef.setLdInst(null); + extRef.setPrefix(null); + extRef.setLnInst(null); + extRef.setDoName(null); + extRef.setDaName(null); + extRef.setServiceType(null); + extRef.setSrcLDInst(null); + extRef.setSrcPrefix(null); + extRef.setSrcLNInst(null); + extRef.setSrcCBName(null); + extRef.unsetLnClass(); + extRef.unsetSrcLNClass(); + } + + private Optional warningReportItem(TExtRef extRef, String message) { + return Optional.of(SclReportItem.warning(extRefXPath(extRef.getDesc()), message)); + } + + private Optional fatalReportItem(TExtRef extRef, String message) { + return Optional.of(SclReportItem.fatal(extRefXPath(extRef.getDesc()), message)); + } + + private String extRefXPath(String extRefDesc) { + return getXPath() + String.format("/ExtRef[%s]", + Utils.xpathAttributeFilter("desc", extRefDesc)); + } + + /** + * Find CompasFlows that match given ExtRef + * + * @param extRef extRef to match + * @param compasFlows list of all CompasFlow in which to search + * @return list of matching CompasFlows + */ + private List getMatchingCompasFlows(TExtRef extRef, List compasFlows) { + return compasFlows.stream().filter(compasFlow -> isMatchingExtRef(compasFlow, extRef)).collect(Collectors.toList()); + } + + /** + * Check if extRef matches CompasFlow + * + * @param compasFlow compasFlow + * @param extRef extRef + * @return true if all required attributes matches. Note that empty string, whitespaces only string and null values are considered as matching + * (missing attributes matches attribute with empty string value or whitespaces only). Return false otherwise. + */ + private boolean isMatchingExtRef(TCompasFlow compasFlow, TExtRef extRef) { + String extRefLnClass = extRef.isSetLnClass() ? extRef.getLnClass().get(0) : null; + return Utils.equalsOrBothBlank(compasFlow.getDataStreamKey(), extRef.getDesc()) + && Utils.equalsOrBothBlank(compasFlow.getExtRefiedName(), extRef.getIedName()) + && Utils.equalsOrBothBlank(compasFlow.getExtRefldinst(), extRef.getLdInst()) + && Utils.equalsOrBothBlank(compasFlow.getExtRefprefix(), extRef.getPrefix()) + && Utils.equalsOrBothBlank(compasFlow.getExtReflnClass(), extRefLnClass) + && Utils.equalsOrBothBlank(compasFlow.getExtReflnInst(), extRef.getLnInst()); + } + + private LDeviceAdapter getLDeviceAdapter() { + return parentAdapter.getParentAdapter(); + } +} 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 a037accc3..6fa771a32 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 @@ -7,9 +7,10 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.lfenergy.compas.scl2007b4.model.TAccessPoint; import org.lfenergy.compas.scl2007b4.model.TLDevice; import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; -import org.lfenergy.compas.scl2007b4.model.TPrivate; +import org.lfenergy.compas.scl2007b4.model.TServer; import org.lfenergy.compas.sct.commons.dto.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclElementAdapter; @@ -28,7 +29,7 @@ *
        *
      1. Adapter
      2. *
          - *
        • {@link LDeviceAdapter#getLNAdapters Returns the value of the LNAdapter containment reference list}
        • + *
        • {@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}
        • *
        @@ -70,8 +71,10 @@ public LDeviceAdapter(IEDAdapter parentAdapter, TLDevice currentElem) { protected boolean amChildElementRef() { return parentAdapter.getCurrentElem().getAccessPoint() .stream() - .filter(tAccessPoint -> tAccessPoint.getServer() != null) - .map(tAccessPoint -> tAccessPoint.getServer().getLDevice()) + .map(TAccessPoint::getServer) + .filter(Objects::nonNull) + .filter(TServer::isSetLDevice) + .map(TServer::getLDevice) .flatMap(Collection::stream) .anyMatch(tlDevice -> currentElem.getInst().equals(tlDevice.getInst())); } @@ -81,6 +84,15 @@ protected String elementXPath() { return String.format("LDevice[%s]", Utils.xpathAttributeFilter("inst", currentElem.isSetInst() ? currentElem.getInst() : null)); } + @Override + public String getXPath() { + if (parentAdapter != null){ + return parentAdapter.getXPath() + "/AccessPoint/Server/" + elementXPath(); + } else { + return super.getXPath(); + } + } + /** * 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 @@ -118,6 +130,14 @@ public LN0Adapter getLN0Adapter(){ return new LN0Adapter(this, currentElem.getLN0()); } + /** + * Checks if LDevice has an LN0 node + * @return true if lDevice has a LN0 node, false otherwise + */ + public boolean hasLN0(){ + return currentElem.isSetLN0(); + } + /** * Gets current LDevice LNodes (except LN0) * @return list of LNAdapter object @@ -140,11 +160,9 @@ public List getLNAdapters(){ public LNAdapter getLNAdapter(String lnClass, String lnInst, String prefix) throws ScdException { return currentElem.getLN() .stream() - .filter(tln -> tln.getLnClass().contains(lnClass) && - tln.getInst().equals(lnInst) && - ( (prefix == null && tln.getPrefix().isEmpty()) || - prefix.equals(tln.getPrefix())) - ) + .filter(tln -> tln.getLnClass().contains(lnClass) + && tln.getInst().equals(lnInst) + && Utils.equalsOrBothBlank(prefix, tln.getPrefix())) .map(tln -> new LNAdapter(this,tln)) .findFirst() .orElseThrow( @@ -166,9 +184,7 @@ public List getExtRefBinders(ExtRefSignalInfo signalInfo) { DataTypeTemplateAdapter dttAdapter = parentAdapter.getParentAdapter().getDataTypeTemplateAdapter(); List potentialBinders = new ArrayList<>(); - List> lnAdapters = new ArrayList<>(); - lnAdapters.add(getLN0Adapter()); - lnAdapters.addAll(getLNAdapters()); + List> lnAdapters = getLNAdaptersInclundigLN0(); for(AbstractLNAdapter lnAdapter : lnAdapters) { String lnType = lnAdapter.getLnType(); try { @@ -193,9 +209,7 @@ public List getExtRefBinders(ExtRefSignalInfo signalInfo) { */ public List getExtRefInfo() { List extRefInfos = new ArrayList<>(); - List> lnAdapters = new ArrayList<>(); - lnAdapters.add(getLN0Adapter()); - lnAdapters.addAll(getLNAdapters()); + List> lnAdapters = getLNAdaptersInclundigLN0(); LogicalNodeOptions logicalNodeOptions = new LogicalNodeOptions(); logicalNodeOptions.setWithExtRef(true); for(AbstractLNAdapter lnAdapter : lnAdapters) { @@ -206,17 +220,16 @@ public List getExtRefInfo() { } /** - * Gets a list of summarized DataTypeTemplate for DataAttribute DAIs (updatable or not) + * Gets a list of summarized DataTypeTemplate for DataAttribute DAIs (updatableOnly or not) * @param rDtt reference resumed DataTypeTemplate (used as filter) - * @param updatable true to retrieve only updatable DAIs, false to retrieve all DAIs - * @return List of ResumedDataTemplate (updatable or not) + * @param updatableOnly true to retrieve only updatableOnly DAIs, false to retrieve all DAIs + * @return List of ResumedDataTemplate (updatableOnly or not) * @throws ScdException SCD illegal arguments exception */ - public Set getDAI(ResumedDataTemplate rDtt, boolean updatable) throws ScdException { + public Set getDAI(ResumedDataTemplate rDtt, boolean updatableOnly) throws ScdException { List> lnAdapters = new ArrayList<>(); if(StringUtils.isBlank(rDtt.getLnClass())){ - lnAdapters.add(getLN0Adapter()); - lnAdapters.addAll(getLNAdapters()); + lnAdapters = getLNAdaptersInclundigLN0(); } else if(rDtt.getLnClass().equals(TLLN0Enum.LLN_0.value())){ lnAdapters.add(getLN0Adapter()); } else { @@ -230,10 +243,28 @@ public Set getDAI(ResumedDataTemplate rDtt, boolean updatab filter.setLnInst(lnAdapter.getLNInst()); filter.setPrefix(lnAdapter.getPrefix()); filter.setLnType(lnAdapter.getLnType()); - resumedDataTemplateSet.addAll(lnAdapter.getDAI(filter, updatable)); + resumedDataTemplateSet.addAll(lnAdapter.getDAI(filter, updatableOnly)); } return resumedDataTemplateSet; } + + public Optional getLDeviceStatus() { + if (!hasLN0()){ + return Optional.empty(); + } + return getLN0Adapter().getLDeviceStatus(); + } + + /** + * Gets all LN of LDevice including LN0 + * @return list of all LN of LDevice + */ + public List> getLNAdaptersInclundigLN0() { + List> aLNAdapters = new ArrayList<>(); + aLNAdapters.add(getLN0Adapter()); + aLNAdapters.addAll(getLNAdapters()); + return aLNAdapters; + } } 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 92deae202..0983b28ba 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 @@ -11,10 +11,9 @@ 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.util.Utils; -import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.Set; import static org.lfenergy.compas.sct.commons.util.CommonConstants.*; @@ -69,6 +68,10 @@ */ public class LN0Adapter extends AbstractLNAdapter { + public static final DoTypeName MOD_DO_TYPE_NAME = new DoTypeName(MOD_DO_NAME); + public static final DaTypeName STVAL_DA_TYPE_NAME = new DaTypeName(STVAL); + public static final DoTypeName BEHAVIOUR_DO_TYPE_NAME = new DoTypeName(BEHAVIOUR_DO_NAME); + public static final DaTypeName BEHAVIOUR_DA_TYPE_NAME = getDaTypeNameForBeh(); /** * Constructor * @param parentAdapter Parent container reference @@ -89,11 +92,10 @@ protected boolean amChildElementRef() { @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)); + return "LN0"; } + /** * Gets current LN0 class type * @return LN0.class @@ -129,6 +131,14 @@ public String getPrefix() { return ""; } + /** + * Gets Inputs node as an adapter + * @return an InputsAdapter + */ + public InputsAdapter getInputsAdapter(){ + return new InputsAdapter(this, currentElem.getInputs()); + } + /** 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 @@ -152,17 +162,18 @@ public void removeAllControlBlocksAndDatasets() { /** * Construct ResumedDataTemplate object with DO and DA attributes - * @param doName The value of the name attribute of DO object + * + * @param doTypeName DoTypeName object * @param daTypeName DaTypeName object * @return ResumedDataTemplate */ - private ResumedDataTemplate getResumedDataTemplate(String doName, DaTypeName daTypeName) { + private ResumedDataTemplate createDaiFilter(DoTypeName doTypeName, DaTypeName daTypeName) { ResumedDataTemplate filter = new ResumedDataTemplate(); filter.setLnClass(getLNClass()); filter.setLnInst(getLNInst()); filter.setPrefix(getPrefix()); filter.setLnType(getLnType()); - filter.setDoName(new DoTypeName(doName)); + filter.setDoName(doTypeName); filter.setDaName(daTypeName); return filter; } @@ -172,42 +183,30 @@ private ResumedDataTemplate getResumedDataTemplate(String doName, DaTypeName daT * @param iedNameLDeviceInstList pair of Ied name and LDevice inst attributes * @return Set of Errors */ - public List checkAndUpdateLDeviceStatus(List> iedNameLDeviceInstList) { - List errors = new ArrayList<>(); + public Optional updateLDeviceStatus(List> iedNameLDeviceInstList) { LDeviceActivation lDeviceActivation = new LDeviceActivation(iedNameLDeviceInstList); final String iedName = getParentAdapter().getParentAdapter().getName(); final String ldInst = getParentAdapter().getInst(); - DaTypeName daTypeNameBeh = new DaTypeName(); - daTypeNameBeh.setName(STVAL); - daTypeNameBeh.setBType(TPredefinedBasicTypeEnum.ENUM); - daTypeNameBeh.setFc(TFCEnum.ST); - ResumedDataTemplate daiBehFilter = getResumedDataTemplate(BEHAVIOUR_DO_NAME, daTypeNameBeh); - List daiBehList = getDAI(daiBehFilter, false); + ResumedDataTemplate daiBehFilter = createDaiFilter(BEHAVIOUR_DO_TYPE_NAME, BEHAVIOUR_DA_TYPE_NAME); + List daiBehList = getDAI(daiBehFilter, false); if (daiBehList.isEmpty()) { - errors.add(buildErrorDescriptionMessage("The LDevice doesn't have a DO @name='Beh' OR its associated DA@fc='ST' AND DA@name='stVal'")); - return errors; + return Optional.of(buildFatalReportItem("The LDevice doesn't have a DO @name='Beh' OR its associated DA@fc='ST' AND DA@name='stVal'")); } Set enumValues = getEnumValues(daiBehList.get(0).getDaName().getType()); - List compasLDevicePrivateList = PrivateService.getCompasPrivates(getParentAdapter().getCurrentElem(), TCompasLDevice.class); + List compasLDevicePrivateList = PrivateService.extractCompasPrivates(getParentAdapter().getCurrentElem(), TCompasLDevice.class); if (compasLDevicePrivateList.isEmpty()) { - errors.add(buildErrorDescriptionMessage("The LDevice doesn't have a Private compas:LDevice.")); - return errors; + return Optional.of(buildFatalReportItem("The LDevice doesn't have a Private compas:LDevice.")); } if (!compasLDevicePrivateList.get(0).isSetLDeviceStatus()) { - errors.add(buildErrorDescriptionMessage("The Private compas:LDevice doesn't have the attribute 'LDeviceStatus'")); - return errors; + return Optional.of(buildFatalReportItem("The Private compas:LDevice doesn't have the attribute 'LDeviceStatus'")); } TCompasLDeviceStatus compasLDeviceStatus = compasLDevicePrivateList.get(0).getLDeviceStatus(); - DaTypeName daTypeNameMod = new DaTypeName(); - daTypeNameMod.setName(STVAL); - ResumedDataTemplate daiModFilter = getResumedDataTemplate(MOD_DO_NAME, daTypeNameMod); - List daiModList = getDAI(daiModFilter, false); - if (daiModList.isEmpty()) { - errors.add(buildErrorDescriptionMessage("The LDevice doesn't have a DO @name='Mod'")); - return errors; + Optional optionalModStVal = getDaiModStVal(); + if (optionalModStVal.isEmpty()) { + return Optional.of(buildFatalReportItem("The LDevice doesn't have a DO @name='Mod'")); } - ResumedDataTemplate newDaModToSetInLN0 = daiModList.get(0); - String initialValue = newDaModToSetInLN0.getDaName().getDaiValues().isEmpty() ? "" : newDaModToSetInLN0.getDaName().getDaiValues().values().toArray()[0].toString(); + ResumedDataTemplate newDaModToSetInLN0 = optionalModStVal.get(); + String initialValue = newDaModToSetInLN0.findFirstValue().orElse(""); lDeviceActivation.checkLDeviceActivationStatus(iedName, ldInst, compasLDeviceStatus, enumValues); if(lDeviceActivation.isUpdatable()){ if(!initialValue.equals(lDeviceActivation.getNewVal())) { @@ -216,18 +215,28 @@ public List checkAndUpdateLDeviceStatus(List getLDeviceStatus() { + return getDaiModStVal() + .flatMap(ResumedDataTemplate::findFirstValue); } + private Optional getDaiModStVal() { + ResumedDataTemplate daiModFilter = createDaiFilter(MOD_DO_TYPE_NAME, STVAL_DA_TYPE_NAME); + return getDAI(daiModFilter, false).stream() + .findFirst(); + } + + private static DaTypeName getDaTypeNameForBeh() { + DaTypeName daTypeNameBeh = new DaTypeName(); + daTypeNameBeh.setName(STVAL); + daTypeNameBeh.setBType(TPredefinedBasicTypeEnum.ENUM); + daTypeNameBeh.setFc(TFCEnum.ST); + return daTypeNameBeh; + } } 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 b6fbe737d..6f56952ee 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 @@ -59,7 +59,6 @@ protected String elementXPath() { 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 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/LDeviceStatus.java similarity index 54% rename from sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/STValEnum.java rename to sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/LDeviceStatus.java index 3b1559172..dcc392540 100644 --- 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/LDeviceStatus.java @@ -6,16 +6,14 @@ package org.lfenergy.compas.sct.commons.util; +import lombok.experimental.UtilityClass; + /** * 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 +@UtilityClass +public class LDeviceStatus { + public static final String ON = "on"; + public static final String OFF = "off"; +} diff --git a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/Utils.java b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/Utils.java index f9346c2e1..fe6b24a01 100644 --- a/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/Utils.java +++ b/sct-commons/src/main/java/org/lfenergy/compas/sct/commons/util/Utils.java @@ -4,7 +4,7 @@ package org.lfenergy.compas.sct.commons.util; -import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import java.util.Collection; import java.util.Objects; @@ -12,7 +12,6 @@ import java.util.function.Predicate; import java.util.stream.Collectors; -@Slf4j public final class Utils { public static final String LEAVING_PREFIX = "<<< Leaving: ::"; @@ -119,4 +118,18 @@ public static String xpathAttributeFilter(String name, Collection value) return xpathAttributeFilter(name, value.stream().filter(Objects::nonNull).collect(Collectors.joining(" "))); } } + + /** + * Checks if strings are equals or both blank. + * Blank means : null, empty string or whitespaces only string. + * @param s1 first string + * @param s2 seconde string + * @return true if strings are equals or both blank, false otherwise + * + * @see org.apache.commons.lang3.StringUtils#isBlank(CharSequence) + */ + public static boolean equalsOrBothBlank(String s1, String s2){ + return Objects.equals(s1, s2) + || (StringUtils.isBlank(s1) && StringUtils.isBlank(s2)); + } } diff --git a/sct-commons/src/main/resources/logback.xml b/sct-commons/src/main/resources/logback.xml deleted file mode 100644 index 6fbe71477..000000000 --- a/sct-commons/src/main/resources/logback.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n - - - - - - - - - - - - \ No newline at end of file diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DTO.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DTO.java index 2ff372b10..194be6745 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DTO.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DTO.java @@ -18,7 +18,8 @@ public class DTO { /* ConnectedAPDTO */ /*-----------------------------------------------*/ public static final String AP_NAME = "AP_NAME"; - public static ConnectedApDTO createCapDTO(){ + + public static ConnectedApDTO createCapDTO() { ConnectedApDTO cap = new ConnectedApDTO(); cap.setApName(AP_NAME); @@ -49,16 +50,16 @@ public static ConnectedApDTO createCapDTO(){ public static final String REMOTE_LN_CLASS = "LN_CLASS_R"; public static final String DA_NAME = P_DA; public static final String DO_NAME = P_DO; - public static final String REMOTE_LN_PREFIX = "PR_R"; + public static final String REMOTE_LN_PREFIX = "LN_PREFIX_R"; public static final String SERVICE_TYPE = P_SERV_T; - public static final String SRC_LD_INST= REMOTE_LD_INST; - public static final String SRC_LN_INST= REMOTE_LN_INST; - public static final String SRC_LN_CLASS= REMOTE_LN_CLASS; - public static final String SRC_PREFIX = REMOTE_LN_PREFIX; + public static final String SRC_LD_INST = "LD_INST_S"; + public static final String SRC_LN_INST = "2"; + public static final String SRC_LN_CLASS = "LN_CLASS_S"; + public static final String SRC_LN_PREFIX = "LN_PREFIX_S"; public static final String SRC_CB_NAME = "SRC_CB_NAME"; - public static TExtRef createExtRef(){ + public static TExtRef createExtRef() { TExtRef tExtRef = new TExtRef(); tExtRef.setDesc(DESC); tExtRef.setPDA(P_DA); @@ -79,14 +80,14 @@ public static TExtRef createExtRef(){ tExtRef.setSrcLDInst(SRC_LD_INST); tExtRef.setSrcLNInst(SRC_LN_INST); tExtRef.getSrcLNClass().add(SRC_LN_CLASS); - tExtRef.setSrcPrefix(SRC_PREFIX); + tExtRef.setSrcPrefix(SRC_LN_PREFIX); tExtRef.setSrcCBName(SRC_CB_NAME); return tExtRef; } - public static ExtRefSignalInfo createExtRefSignalInfo(){ + public static ExtRefSignalInfo createExtRefSignalInfo() { ExtRefSignalInfo signalInfo = new ExtRefSignalInfo(); signalInfo.setDesc(DESC); signalInfo.setPDA(P_DA); @@ -98,7 +99,7 @@ public static ExtRefSignalInfo createExtRefSignalInfo(){ return signalInfo; } - public static ExtRefBindingInfo createExtRefBindingInfo(){ + public static ExtRefBindingInfo createExtRefBindingInfo_Remote() { ExtRefBindingInfo bindingInfo = new ExtRefBindingInfo(); bindingInfo.setIedName(REMOTE_IED_NAME); bindingInfo.setLdInst(REMOTE_LD_INST); @@ -112,28 +113,43 @@ public static ExtRefBindingInfo createExtRefBindingInfo(){ return bindingInfo; } - public static ExtRefSourceInfo createExtRefSourceInfo(){ + public static ExtRefBindingInfo createExtRefBindingInfo_Source() { + ExtRefBindingInfo bindingInfo = new ExtRefBindingInfo(); + bindingInfo.setIedName(HOLDER_IED_NAME); + bindingInfo.setLdInst(HOLDER_LD_INST); + bindingInfo.setLnInst(SRC_LN_INST); + bindingInfo.setLnClass(SRC_LN_CLASS); + bindingInfo.setDaName(new DaTypeName(DA_NAME)); + bindingInfo.setDoName(new DoTypeName(DO_NAME)); + bindingInfo.setPrefix(REMOTE_LN_PREFIX); + bindingInfo.setServiceType(TServiceType.fromValue(SERVICE_TYPE)); + + return bindingInfo; + } + + public static ExtRefSourceInfo createExtRefSourceInfo() { ExtRefSourceInfo sourceInfo = new ExtRefSourceInfo(); sourceInfo.setSrcLDInst(SRC_LD_INST); sourceInfo.setSrcLNInst(SRC_LN_INST); sourceInfo.setSrcLNClass(SRC_LN_CLASS); - sourceInfo.setSrcPrefix(SRC_PREFIX); + sourceInfo.setSrcPrefix(SRC_LN_PREFIX); sourceInfo.setSrcCBName(SRC_CB_NAME); return sourceInfo; } - public static ExtRefInfo createExtRefInfo(){ + public static ExtRefInfo createExtRefInfo() { ExtRefInfo extRefInfo = new ExtRefInfo(); extRefInfo.setMetaData(createMetaDataInfo()); extRefInfo.setSourceInfo(DTO.createExtRefSourceInfo()); - extRefInfo.setBindingInfo(DTO.createExtRefBindingInfo()); + extRefInfo.setBindingInfo(DTO.createExtRefBindingInfo_Remote()); extRefInfo.setSignalInfo(DTO.createExtRefSignalInfo()); return extRefInfo; } - public static LNodeMetaData createMetaDataInfo(){ + + public static LNodeMetaData createMetaDataInfo() { LNodeMetaData metaData = new LNodeMetaData(); metaData.setIedName(HOLDER_IED_NAME); metaData.setLdInst(HOLDER_LD_INST); @@ -144,7 +160,6 @@ public static LNodeMetaData createMetaDataInfo(){ } - /*-----------------------------------------------*/ /* ResumedDataTemplate */ /*-----------------------------------------------*/ @@ -152,7 +167,8 @@ public static LNodeMetaData createMetaDataInfo(){ public static final String CDC = TPredefinedCDCEnum.WYE.value(); public static final String FC = TFCEnum.CF.value(); - public static ResumedDataTemplate createRTT(){ + + public static ResumedDataTemplate createRTT() { ResumedDataTemplate rDTT = new ResumedDataTemplate(); rDTT.setLnType(LN_TYPE); @@ -165,7 +181,7 @@ public static ResumedDataTemplate createRTT(){ return rDTT; } - public static ResumedDataTemplate createRTT(String prefix, String lnClass, String lnInst){ + public static ResumedDataTemplate createRTT(String prefix, String lnClass, String lnInst) { ResumedDataTemplate rDTT = new ResumedDataTemplate(); rDTT.setLnType(LN_TYPE); @@ -208,7 +224,7 @@ public static TRptEnabled createTRptEnabled() { return rptEnabled; } - public static TReportControl.OptFields createOptFields(){ + public static TReportControl.OptFields createOptFields() { TReportControl.OptFields optFields = new TReportControl.OptFields(); optFields.setBufOvfl(true); optFields.setBufOvfl(true); @@ -219,15 +235,16 @@ public static TReportControl.OptFields createOptFields(){ /*-----------------------------------------------*/ /* LNodeDTO */ /*-----------------------------------------------*/ - public static LNodeDTO createLNodeDTO(){ - return new LNodeDTO(HOLDER_LN_INST, HOLDER_LN_CLASS,null,LN_TYPE); + public static LNodeDTO createLNodeDTO() { + return new LNodeDTO(HOLDER_LN_INST, HOLDER_LN_CLASS, null, LN_TYPE); } /*-----------------------------------------------*/ /* LDeviceDTO */ /*-----------------------------------------------*/ public static final String LD_NAME = "LDPO"; - public static LDeviceDTO createLdDTO(){ + + public static LDeviceDTO createLdDTO() { LDeviceDTO lDeviceDTO = new LDeviceDTO(); lDeviceDTO.setLdInst(HOLDER_LD_INST); @@ -242,7 +259,7 @@ public static LDeviceDTO createLdDTO(){ /* IedDTO */ /*-----------------------------------------------*/ - public static IedDTO createIedDTO(){ + public static IedDTO createIedDTO() { IedDTO iedDTO = new IedDTO(); iedDTO.setName(HOLDER_IED_NAME); @@ -254,7 +271,7 @@ public static IedDTO createIedDTO(){ /* FCDAInfo */ /*-----------------------------------------------*/ - public static TFCDA createFCDA(){ + public static TFCDA createFCDA() { TFCDA tfcda = new TFCDA(); tfcda.setDaName("da.bda"); tfcda.setDoName("do.sdo"); @@ -272,7 +289,8 @@ public static TFCDA createFCDA(){ /*-----------------------------------------------*/ public static final String NOW_STR = LocalDateTime.now().toString(); - public static HeaderDTO createHeaderDTO(UUID id){ + + public static HeaderDTO createHeaderDTO(UUID id) { HeaderDTO headerDTO = new HeaderDTO(); headerDTO.setId(id); headerDTO.setRevision("1.0"); @@ -281,7 +299,7 @@ public static HeaderDTO createHeaderDTO(UUID id){ return headerDTO; } - public static HeaderDTO.HistoryItem createHeaderItem(String now){ + public static HeaderDTO.HistoryItem createHeaderItem(String now) { HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem(); historyItem.setRevision("1.0"); historyItem.setVersion("1.0"); @@ -293,7 +311,5 @@ public static HeaderDTO.HistoryItem createHeaderItem(String now){ return historyItem; } - public static final Map, List> comMap = Map.of( - Pair.of("RSPACE_PROCESS_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString()), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), - Pair.of("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString()), Arrays.asList("ADMIN_AP","TATA_AP_EFFACEC")); + public static final Map, List> comMap = Map.of(Pair.of("RSPACE_PROCESS_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString()), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"), Pair.of("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString()), Arrays.asList("ADMIN_AP", "TATA_AP_EFFACEC")); } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DaTypeNameTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DaTypeNameTest.java index bc7ddf010..4e399151b 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DaTypeNameTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/DaTypeNameTest.java @@ -5,9 +5,13 @@ package org.lfenergy.compas.sct.commons.dto; import org.junit.jupiter.api.Test; +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.TFCEnum; import java.util.Map; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDa; @@ -122,4 +126,37 @@ void testFrom() { // then assertThat(da2).isEqualTo(da1); } + + /** + * ListFcEnum = CF, DC, SG, SP, ST , SE + * Fc value should be in ListFcEnum to be considered as known + */ + @Test + void isUpdatable_shouldReturnTrue_whenFcKnown_And_valImportIsTrue() { + // given + DaTypeName da1 = createDa("da1.bda1.bda2", TFCEnum.CF, true, Map.of(0L, "value")); + // when + boolean isDAUpdatable = da1.isUpdatable(); + // then + assertThat(isDAUpdatable).isTrue(); + } + + @ParameterizedTest + @MethodSource("daParametersProvider") + void isUpdatable(String testName, TFCEnum fc, boolean valImport) { + // given + DaTypeName da1 = createDa("da1.bda1.bda2", fc, valImport, Map.of(0L, "value")); + // when + boolean isDAUpdatable = da1.isUpdatable(); + // then + assertThat(isDAUpdatable).isFalse(); + } + + private static Stream daParametersProvider() { + return Stream.of( + Arguments.of("should return false when ", TFCEnum.MX, true), + Arguments.of("should return false when ",TFCEnum.CF, false) + ); + } + } 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 6157d3815..68024e00c 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 @@ -6,22 +6,22 @@ import org.junit.jupiter.api.Test; import org.lfenergy.compas.scl2007b4.model.TExtRef; -import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; import org.lfenergy.compas.scl2007b4.model.TServiceType; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; class ExtRefBindingInfoTest { @Test - void testConstruction(){ - ExtRefBindingInfo bindingInfo = DTO.createExtRefBindingInfo(); - ExtRefBindingInfo bindingInfo_bis = DTO.createExtRefBindingInfo(); + void testConstruction() { + ExtRefBindingInfo bindingInfo = DTO.createExtRefBindingInfo_Remote(); + ExtRefBindingInfo bindingInfo_bis = DTO.createExtRefBindingInfo_Remote(); ExtRefBindingInfo bindingInfo_ter = new ExtRefBindingInfo(DTO.createExtRef()); ExtRefBindingInfo bindingInfo_qt = new ExtRefBindingInfo(); - assertEquals(bindingInfo,bindingInfo_ter); - assertEquals(bindingInfo,bindingInfo_bis); + assertEquals(bindingInfo, bindingInfo_ter); + assertEquals(bindingInfo, bindingInfo_bis); assertNotEquals(null, bindingInfo); assertNotEquals(bindingInfo, bindingInfo_qt); bindingInfo_qt.setDaName(bindingInfo.getDaName()); @@ -51,8 +51,8 @@ void testConstruction(){ } @Test - void testIsValid(){ - ExtRefBindingInfo bindingInfo = DTO.createExtRefBindingInfo(); + void testIsValid() { + ExtRefBindingInfo bindingInfo = DTO.createExtRefBindingInfo_Remote(); assertTrue(bindingInfo.isValid()); bindingInfo.setLnClass("PIOC"); bindingInfo.setLnInst(""); @@ -71,7 +71,7 @@ void testIsValid(){ } @Test - void testIsWrappedIn(){ + void testIsWrappedIn() { TExtRef extRef = DTO.createExtRef(); ExtRefBindingInfo bindingInfo = new ExtRefBindingInfo(); assertFalse(bindingInfo.isWrappedIn(extRef)); @@ -82,7 +82,7 @@ void testIsWrappedIn(){ bindingInfo.setLdInst(extRef.getLdInst()); assertFalse(bindingInfo.isWrappedIn(extRef)); - if(!extRef.getLnClass().isEmpty()) { + if (!extRef.getLnClass().isEmpty()) { bindingInfo.setLnClass(extRef.getLnClass().get(0)); assertFalse(bindingInfo.isWrappedIn(extRef)); @@ -98,11 +98,50 @@ void testIsWrappedIn(){ } @Test - void testIsNull(){ + void testIsNull() { ExtRefBindingInfo bindingInfo = new ExtRefBindingInfo(); assertTrue(bindingInfo.isNull()); bindingInfo.setServiceType(TServiceType.REPORT); assertFalse(bindingInfo.isNull()); } + + @Test + void compareTo_should_return_0_when_ExtRefBindingInfo_the_same() { + // Given + ExtRefBindingInfo bindingInfo1 = DTO.createExtRefBindingInfo_Remote(); + ExtRefBindingInfo bindingInfo2 = DTO.createExtRefBindingInfo_Remote(); + + // When + int result = bindingInfo1.compareTo(bindingInfo2); + + // Then + assertThat(result).isZero(); + } + + @Test + void compareTo_should_return_positive_int_when_first_ExtRefBindingInfo_is_major_in_alphabetical_order() { + // Given + ExtRefBindingInfo bindingInfo1 = DTO.createExtRefBindingInfo_Remote(); + ExtRefBindingInfo bindingInfo2 = DTO.createExtRefBindingInfo_Source(); + + // When + int result = bindingInfo1.compareTo(bindingInfo2); + + // Then + assertThat(result).isPositive(); + } + + @Test + void compareTo_should_return_negative_int_when_first_ExtRefBindingInfo_is_minor_in_alphabetical_order() { + // Given + ExtRefBindingInfo bindingInfo1 = DTO.createExtRefBindingInfo_Source(); + ExtRefBindingInfo bindingInfo2 = DTO.createExtRefBindingInfo_Remote(); + + // When + int result = bindingInfo1.compareTo(bindingInfo2); + + // Then + assertThat(result).isNegative(); + } } \ No newline at end of file diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ExtRefInfoTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ExtRefInfoTest.java index c5e3598ab..fe3da128d 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ExtRefInfoTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ExtRefInfoTest.java @@ -5,10 +5,16 @@ package org.lfenergy.compas.sct.commons.dto; import org.junit.jupiter.api.Test; +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.TExtRef; import org.lfenergy.compas.scl2007b4.model.TFCDA; import org.lfenergy.compas.scl2007b4.model.TServiceType; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; class ExtRefInfoTest { @@ -86,10 +92,84 @@ void testMatchTFCDA(){ private ExtRefInfo createExtRef(){ ExtRefInfo extRefInfo = new ExtRefInfo(); extRefInfo.setSignalInfo(DTO.createExtRefSignalInfo()); - extRefInfo.setBindingInfo(DTO.createExtRefBindingInfo()); + extRefInfo.setBindingInfo(DTO.createExtRefBindingInfo_Remote()); extRefInfo.setSourceInfo(DTO.createExtRefSourceInfo()); return extRefInfo; } + @Test + void checkMatchingFCDA_shouldreturnTrue_whenContentMatch() { + //Given + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setBindingInfo(DTO.createExtRefBindingInfo_Remote()); + extRefInfo.setSignalInfo(DTO.createExtRefSignalInfo()); + + TFCDA tfcda = new TFCDA(); + tfcda.setLdInst(DTO.createExtRefBindingInfo_Remote().getLdInst()); + tfcda.getLnClass().add(DTO.createExtRefBindingInfo_Remote().getLnClass()); + tfcda.setLnInst(DTO.createExtRefBindingInfo_Remote().getLnInst()); + tfcda.setPrefix(DTO.createExtRefBindingInfo_Remote().getPrefix()); + tfcda.setDoName(DTO.createExtRefSignalInfo().getPDO()); + tfcda.setDaName(DTO.createExtRefSignalInfo().getPDA()); + + //When Then + assertThat(extRefInfo.checkMatchingFCDA(tfcda)).isTrue(); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("provideIncompleteExtRefInfo") + void checkMatchingFCDA(String testCase, TFCDA fcda, ExtRefBindingInfo bindingInfo, ExtRefSignalInfo signalInfo) { + //Given + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setBindingInfo(bindingInfo); + extRefInfo.setSignalInfo(signalInfo); + //When Then + assertThat(extRefInfo.checkMatchingFCDA(fcda)).isFalse(); + } + + + private static Stream provideIncompleteExtRefInfo() { + + ExtRefBindingInfo bindingInfo = DTO.createExtRefBindingInfo_Remote(); + ExtRefSignalInfo signalInfo = DTO.createExtRefSignalInfo(); + + ExtRefBindingInfo extRefBindingInfoLDInstNotMatch = DTO.createExtRefBindingInfo_Remote(); + extRefBindingInfoLDInstNotMatch.setLdInst("ldInst"); + + ExtRefBindingInfo extRefBindingInfoLNClassNotMatch = DTO.createExtRefBindingInfo_Remote(); + extRefBindingInfoLNClassNotMatch.setLnClass("lnClass"); + + ExtRefBindingInfo xtRefBindingInfoLNInstNotMatch = DTO.createExtRefBindingInfo_Remote(); + xtRefBindingInfoLNInstNotMatch.setLnInst("5"); + + ExtRefBindingInfo ExtRefBindingInfoPrefixNotMatch = DTO.createExtRefBindingInfo_Remote(); + ExtRefBindingInfoPrefixNotMatch.setPrefix("Pref"); + + ExtRefSignalInfo extRefSignalInfoDOnotMatch = DTO.createExtRefSignalInfo(); + extRefSignalInfoDOnotMatch.setPDO("do"); + + ExtRefSignalInfo extRefSignalInfoDAnotMatch = DTO.createExtRefSignalInfo(); + extRefSignalInfoDAnotMatch.setPDA("da"); + + TFCDA tfcda = new TFCDA(); + tfcda.setLdInst(DTO.createExtRefBindingInfo_Remote().getLdInst()); + tfcda.getLnClass().add(DTO.createExtRefBindingInfo_Remote().getLnClass()); + tfcda.setLnInst(DTO.createExtRefBindingInfo_Remote().getLnInst()); + tfcda.setPrefix(DTO.createExtRefBindingInfo_Remote().getPrefix()); + tfcda.setDoName(DTO.createExtRefSignalInfo().getPDO()); + tfcda.setDaName(DTO.createExtRefSignalInfo().getPDA()); + + return Stream.of( + Arguments.of("return false when binding and signal are null ", tfcda, null, null), + Arguments.of("return false when only signal is null ", tfcda, bindingInfo, null), + Arguments.of("return false when only binding is null ", tfcda, null, signalInfo), + Arguments.of("return false when ldInst not match ", tfcda, extRefBindingInfoLDInstNotMatch, signalInfo), + Arguments.of("return false when lnClass not match ", tfcda, extRefBindingInfoLNClassNotMatch, signalInfo), + Arguments.of("return false when lNInst not match ", tfcda, xtRefBindingInfoLNInstNotMatch, signalInfo), + Arguments.of("return false when prefix not match ", tfcda, ExtRefBindingInfoPrefixNotMatch, signalInfo), + Arguments.of("return false when pDO not match ",tfcda, bindingInfo, extRefSignalInfoDOnotMatch), + Arguments.of("return false when pDA not match ",tfcda, bindingInfo, extRefSignalInfoDAnotMatch) + ); + } } \ No newline at end of file diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/FCDAInfoTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/FCDAInfoTest.java index 7b7121466..1b730c708 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/FCDAInfoTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/FCDAInfoTest.java @@ -5,10 +5,17 @@ package org.lfenergy.compas.sct.commons.dto; import org.junit.jupiter.api.Test; +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.TFCDA; import org.lfenergy.compas.scl2007b4.model.TFCEnum; -import static org.junit.jupiter.api.Assertions.*; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; class FCDAInfoTest { @@ -50,4 +57,68 @@ void testConstructor(){ assertTrue(fcdaInfo1.isValid()); } + + @ParameterizedTest(name = "{0}") + @MethodSource("providerFCDAInfoObjects") + void checkFCDACompatibilitiesForBinding(String testCase, FCDAInfo fcdaInfo, FCDAInfo expectedFcdaInfo) { + assertThat(fcdaInfo.checkFCDACompatibilitiesForBinding(expectedFcdaInfo)).isFalse(); + } + + @Test + void checkFCDACompatibilitiesForBinding_shouldReturnTrue_whensameContent() { + //Given + TFCDA tfcda = new TFCDA(); + tfcda.setLdInst(DTO.createExtRefBindingInfo_Remote().getLdInst()); + tfcda.getLnClass().add(DTO.createExtRefBindingInfo_Remote().getLnClass()); + tfcda.setLnInst(DTO.createExtRefBindingInfo_Remote().getLnInst()); + tfcda.setDoName(DTO.createExtRefSignalInfo().getPDO()); + tfcda.setDaName(DTO.createExtRefSignalInfo().getPDA()); + + FCDAInfo fcdaInfo = new FCDAInfo(tfcda); + FCDAInfo expectedFcdaInfo = new FCDAInfo(tfcda); + //When Then + assertThat(fcdaInfo.checkFCDACompatibilitiesForBinding(expectedFcdaInfo)).isTrue(); + } + + private static Stream providerFCDAInfoObjects(){ + + TFCDA tfcda = new TFCDA(); + tfcda.setLdInst(DTO.createExtRefBindingInfo_Remote().getLdInst()); + tfcda.getLnClass().add(DTO.createExtRefBindingInfo_Remote().getLnClass()); + tfcda.setLnInst(DTO.createExtRefBindingInfo_Remote().getLnInst()); + tfcda.setDoName(DTO.createExtRefSignalInfo().getPDO()); + tfcda.setDaName(DTO.createExtRefSignalInfo().getPDA()); + + FCDAInfo fcdaInfo = new FCDAInfo(tfcda); + + FCDAInfo expectedFcdaInfo = new FCDAInfo(tfcda); + + FCDAInfo expectedLDInstNotMatch = new FCDAInfo(tfcda); + expectedLDInstNotMatch.setLdInst("LDCMDDJ"); + + FCDAInfo expectedLNClassNotMatch = new FCDAInfo(tfcda); + expectedLNClassNotMatch.setLnClass("CSWI"); + + FCDAInfo expectedLNInstNotMatch = new FCDAInfo(tfcda); + expectedLNInstNotMatch.setLnInst("5"); + + FCDAInfo expectedPrefixNotMatch = new FCDAInfo(tfcda); + expectedPrefixNotMatch.setPrefix("Prefix"); + + FCDAInfo expectedDONotMatch = new FCDAInfo(tfcda); + expectedDONotMatch.setDoName(new DoTypeName("do.do1")); + + FCDAInfo expectedDANotMatch = new FCDAInfo(tfcda); + expectedDANotMatch.setDaName(new DaTypeName("da.bda.bda1")); + + return Stream.of( + Arguments.of("return false when LdInst not match ", fcdaInfo, expectedLDInstNotMatch), + Arguments.of("return false when lnClass not match ", fcdaInfo, expectedLNClassNotMatch), + Arguments.of("return false when lnInst not match ", fcdaInfo, expectedLNInstNotMatch), + Arguments.of("return false when Prefix not match ", fcdaInfo, expectedPrefixNotMatch), + Arguments.of("return false when DO not match ", fcdaInfo, expectedDONotMatch), + Arguments.of("return false when DO not match ", fcdaInfo, expectedDANotMatch) + + ); + } } \ No newline at end of file diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/LDeviceDTOTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/LDeviceDTOTest.java index 26b95816c..b020752f8 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/LDeviceDTOTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/LDeviceDTOTest.java @@ -5,9 +5,6 @@ package org.lfenergy.compas.sct.commons.dto; -import lombok.extern.slf4j.Slf4j; -import static org.junit.jupiter.api.Assertions.*; - import org.junit.jupiter.api.Test; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; @@ -15,10 +12,10 @@ import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; - import java.util.Set; -@Slf4j +import static org.junit.jupiter.api.Assertions.*; + class LDeviceDTOTest { @Test @@ -56,4 +53,4 @@ void testFromLDAdapter() throws Exception { LDeviceDTO lDeviceDTO = LDeviceDTO.from(lDeviceAdapter,null); assertNotNull(lDeviceDTO); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ReportControlBlockTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ReportControlBlockTest.java index 0b8256cc8..a2cc6bea8 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ReportControlBlockTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ReportControlBlockTest.java @@ -5,16 +5,7 @@ package org.lfenergy.compas.sct.commons.dto; import org.junit.jupiter.api.Test; -import org.lfenergy.compas.scl2007b4.model.TClientLN; -import org.lfenergy.compas.scl2007b4.model.TControlWithIEDName; -import org.lfenergy.compas.scl2007b4.model.TPredefinedTypeOfSecurityEnum; -import org.lfenergy.compas.scl2007b4.model.TReportControl; -import org.lfenergy.compas.scl2007b4.model.TReportSettings; -import org.lfenergy.compas.scl2007b4.model.TRptEnabled; -import org.lfenergy.compas.scl2007b4.model.TServiceSettingsNoDynEnum; -import org.lfenergy.compas.scl2007b4.model.TServiceType; -import org.lfenergy.compas.scl2007b4.model.TServices; -import org.lfenergy.compas.scl2007b4.model.TText; +import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.exception.ScdException; import org.lfenergy.compas.sct.commons.scl.SclRootAdapter; import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; @@ -27,12 +18,7 @@ import java.util.Optional; import java.util.UUID; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; class ReportControlBlockTest { @@ -234,4 +220,4 @@ private TReportControl.OptFields createOptFields(){ optFields.setDataRef(true); return optFields; } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplateTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplateTest.java index 385eda9e6..691a82145 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplateTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/dto/ResumedDataTemplateTest.java @@ -5,17 +5,27 @@ package org.lfenergy.compas.sct.commons.dto; import org.junit.jupiter.api.Test; +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.TFCEnum; import org.lfenergy.compas.scl2007b4.model.TPredefinedCDCEnum; import org.lfenergy.compas.scl2007b4.model.TVal; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; +import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDa; +import static org.lfenergy.compas.sct.commons.util.CommonConstants.MOD_DO_NAME; +import static org.lfenergy.compas.sct.commons.util.CommonConstants.STVAL; class ResumedDataTemplateTest { + public static final String CTL_MODEL = "ctlModel"; @Test void testGetObjRef(){ String expected = "IEDLDTM/prelnclass1.do.sdo1.sdo2.da.bda1.bda2"; @@ -148,12 +158,95 @@ void testCopyFrom() { assertThrows(IllegalArgumentException.class, () -> rDtt_t.setFc(TFCEnum.BL)); } + /** + * Known Fc = CF, DC, SG, SP, ST , SE + */ + @ParameterizedTest + @MethodSource("daParametersProviderUpdatable") + void isUpdatable_case0(String testName, String daName, TFCEnum fc, boolean valImport) { + //Given + ResumedDataTemplate rDTT = new ResumedDataTemplate(); + rDTT.setDoName(new DoTypeName(MOD_DO_NAME)); + rDTT.setDaName(new DaTypeName(daName)); + rDTT.setFc(fc); + rDTT.setValImport(valImport); + //When + boolean isRdttUpdatable = rDTT.isUpdatable(); + // Then + assertThat(isRdttUpdatable).isTrue(); + } + + private static Stream daParametersProviderUpdatable() { + return Stream.of( + Arguments.of("should return true when Mod", STVAL, TFCEnum.CF, true), + Arguments.of("should return true when Mod", STVAL, TFCEnum.CF, false), + Arguments.of("should return true when Mod", STVAL, TFCEnum.MX, true), + Arguments.of("should return true when Mod", STVAL, TFCEnum.MX, false), + Arguments.of("should return true when Mod", STVAL, null, true), + Arguments.of("should return true when Mod", STVAL, null, false), + Arguments.of("should return true when Mod", CTL_MODEL, TFCEnum.CF, true) + ); + } + + @ParameterizedTest + @MethodSource("daParametersProviderNotUpdatable") + void isUpdatable_case1(String testName, String daName, TFCEnum fc, boolean valImport) { + //Given + ResumedDataTemplate rDTT = new ResumedDataTemplate(); + rDTT.setDoName(new DoTypeName(MOD_DO_NAME)); + rDTT.setDaName(new DaTypeName(daName)); + rDTT.setFc(fc); + rDTT.setValImport(valImport); + //When + boolean isRdttUpdatable = rDTT.isUpdatable(); + // Then + assertThat(isRdttUpdatable).isFalse(); + } + + private static Stream daParametersProviderNotUpdatable() { + return Stream.of( + Arguments.of("should return false when Mod", CTL_MODEL, TFCEnum.CF, false), + Arguments.of("should return false when Mod", CTL_MODEL, TFCEnum.MX, true), + Arguments.of("should return false when Mod", CTL_MODEL, TFCEnum.MX, false), + Arguments.of("should return false when Mod", CTL_MODEL, null, true), + Arguments.of("should return false when Mod", CTL_MODEL, null, false) + ); + } + @Test - void testIsUpdatable(){ - ResumedDataTemplate rDtt = DTO.createRTT("pre","lnclass","1"); - assertTrue(rDtt.isUpdatable()); + void findFirstValue_should_return_value(){ + // Given + ResumedDataTemplate rDTT = new ResumedDataTemplate(); + DaTypeName da1 = createDa("da1", TFCEnum.CF, true, Map.of(10L, "a value")); + rDTT.setDaName(da1); + // When + Optional firstValue = rDTT.findFirstValue(); + // Then + assertThat(firstValue).hasValue("a value"); + } - rDtt.getDaName().setFc(TFCEnum.BL); - assertFalse(rDtt.isUpdatable()); + @Test + void findFirstValue_should_return_first_value(){ + // Given + ResumedDataTemplate rDTT = new ResumedDataTemplate(); + DaTypeName da1 = createDa("da1", TFCEnum.CF, true, + Map.of(1L, "value 1", 0L, "value 0")); + rDTT.setDaName(da1); + // When + Optional firstValue = rDTT.findFirstValue(); + // Then + assertThat(firstValue).hasValue("value 0"); + } + + @Test + void findFirstValue_should_return_empty_optional(){ + // Given + ResumedDataTemplate rDTT = new ResumedDataTemplate(); + DaTypeName da1 = createDa("da1", TFCEnum.CF, true, Map.of()); + rDTT.setDaName(da1); + // When + Optional firstValue = rDTT.findFirstValue(); + // Then + assertThat(firstValue).isNotPresent(); } } 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 new file mode 100644 index 000000000..617ebea50 --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ExtRefServiceTest.java @@ -0,0 +1,232 @@ +// SPDX-FileCopyrightText: 2021 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.scl; + +import org.junit.jupiter.api.Test; +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.SCL; +import org.lfenergy.compas.scl2007b4.model.TCompasFlow; +import org.lfenergy.compas.scl2007b4.model.TExtRef; +import org.lfenergy.compas.scl2007b4.model.TInputs; +import org.lfenergy.compas.sct.commons.dto.SclReport; +import org.lfenergy.compas.sct.commons.dto.SclReportItem; +import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter; +import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter; +import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; +import org.opentest4j.AssertionFailedError; + +import java.util.Optional; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +class ExtRefServiceTest { + + @Test + void updateAllExtRefIedNames_should_update_iedName_and_ExtRefiedName() throws Exception { + // Given : An ExtRef with a matching compas:Flow + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_success.xml"); + // When + SclReport sclReport = ExtRefService.updateAllExtRefIedNames(scd); + // Then + TExtRef extRef = findExtRef(sclReport, "IED_NAME1", "LD_INST11", "STAT_LDSUIED_LPDO 1 Sortie_13_BOOLEAN_18_stVal_1"); + assertThat(extRef.getIedName()).isEqualTo("IED_NAME2"); + + TInputs inputs = findLDeviceAdapter(sclReport, "IED_NAME1", "LD_INST11") + .getLN0Adapter() + .getCurrentElem() + .getInputs(); + assertThat(PrivateService.extractCompasPrivate(inputs, TCompasFlow.class)) + .map(TCompasFlow::getExtRefiedName) + .hasValue("IED_NAME2"); + } + + @Test + void updateAllExtRefIedNames_should_return_success_status() throws Exception { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_success.xml"); + // When + SclReport sclReport = ExtRefService.updateAllExtRefIedNames(scd); + // Then + assertThat(sclReport.isSuccess()) + .overridingErrorMessage(String.valueOf(sclReport.getSclReportItems())) + .isTrue(); + } + + @ParameterizedTest(name = "{0}") + @MethodSource("updateAllExtRefIedNamesErrors") + void updateAllExtRefIedNames_should_report_errors(String testCase, SCL scl, SclReportItem... errors) { + // Given : scl parameter + // When + SclReport sclReport = ExtRefService.updateAllExtRefIedNames(scl); + // Then : the sclReport should report all errors described in the comments in the SCD file + assertThat(sclReport).isNotNull(); + assertThat(sclReport.isSuccess()).isFalse(); + assertThat(sclReport.getSclReportItems()).containsExactlyInAnyOrder(errors); + } + + public static Stream updateAllExtRefIedNamesErrors() throws Exception { + return + Stream.of(Arguments.of( + "Errors on ExtRefs", + SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml"), + new SclReportItem[]{ + SclReportItem.fatal( + "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]" + + "/LN0/Inputs/ExtRef[@desc=\"No matching compas:Flow\"]", + "The signal ExtRef has no matching compas:Flow Private"), + SclReportItem.fatal( + "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]" + + "/LN0/Inputs/ExtRef[@desc=\"Matching two compas:Flow\"]", + "The signal ExtRef has more than one matching compas:Flow Private"), + SclReportItem.fatal( + "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST13\"]", + "The LDevice status is neither \"on\" nor \"off\""), + SclReportItem.fatal( + "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST14\"]", + "The LDevice status is undefined"), + SclReportItem.warning( + "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]" + + "/LN0/Inputs/ExtRef[@desc=\"ExtRef does not match any ICDSystemVersionUUID\"]", + "The signal ExtRef iedName does not match any IED/Private/compas:ICDHeader@ICDSystemVersionUUID"), + SclReportItem.warning( + "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]" + + "/LN0/Inputs/ExtRef[@desc=\"ExtRefldinst does not match any LDevice inst in source IED\"]", + "The signal ExtRef ExtRefldinst does not match any LDevice with same inst attribute in source IED /SCL/IED[@name=\"IED_NAME2\"]"), + SclReportItem.warning( + "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]" + + "/LN0/Inputs/ExtRef[@desc=\"ExtRef does not match any LN is source LDevice\"]", + "The signal ExtRef ExtRefldinst does not match any LDevice with same inst attribute in source IED /SCL/IED[@name=\"IED_NAME2\"]"), + SclReportItem.warning( + "/SCL/IED[@name=\"IED_NAME1\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST11\"]" + + "/LN0/Inputs/ExtRef[@desc=\"Source LDevice is off for this ExtRef\"]", + "The signal ExtRef source LDevice /SCL/IED[@name=\"IED_NAME2\"]/AccessPoint/Server/LDevice[@inst=\"LD_INST22\"] status is off"), + 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") + }), + Arguments.of( + "Errors on IEDs", + SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_ied_errors.xml"), + new SclReportItem[]{ + SclReportItem.fatal( + "/SCL/IED[@name=\"IED_NAME1\"], /SCL/IED[@name=\"IED_NAME2\"]", + "/IED/Private/compas:ICDHeader[@ICDSystemVersionUUID] must be unique but the same ICDSystemVersionUUID was found on several IED."), + SclReportItem.fatal("/SCL/IED[@name=\"IED_NAME3\"]", "IED has no Private COMPAS-ICDHeader element"), + SclReportItem.fatal("/SCL/IED[@name=\"IED_NAME4\"]", "IED private COMPAS-ICDHeader as no icdSystemVersionUUID or iedName attribute"), + SclReportItem.fatal("/SCL/IED[@name=\"IED_NAME5\"]", "IED private COMPAS-ICDHeader as no icdSystemVersionUUID or iedName attribute") + }) + ); + } + + @Test + void updateAllExtRefIedNames_when_not_bindable_should_clear_binding() throws Exception { + // Given : see comments in SCD file + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml"); + // When + SclReport sclReport = ExtRefService.updateAllExtRefIedNames(scd); + // Then + assertThatExtRefBindingInfoIsMissing(findExtRef(sclReport, "IED_NAME1", "LD_INST12", "ExtRef target LDevice status is off")); + assertThatExtRefBindingInfoIsMissing(findExtRef(sclReport, "IED_NAME1", "LD_INST11", "Match compas:Flow but FlowStatus is INACTIVE")); + assertThatExtRefBindingInfoIsMissing(findExtRef(sclReport, "IED_NAME1", "LD_INST11", "ExtRef does not match any ICDSystemVersionUUID")); + assertThatExtRefBindingInfoIsMissing(findExtRef(sclReport, "IED_NAME1", "LD_INST11", "ExtRefldinst does not match any LDevice inst in source IED")); + assertThatExtRefBindingInfoIsMissing(findExtRef(sclReport, "IED_NAME1", "LD_INST11", "ExtRef does not match any LN is source LDevice")); + assertThatExtRefBindingInfoIsMissing(findExtRef(sclReport, "IED_NAME1", "LD_INST11", "Source LDevice is off for this ExtRef")); + } + + private void assertThatExtRefBindingInfoIsMissing(TExtRef extRef) { + assertThat(extRef.isSetIedName()).isFalse(); + assertThat(extRef.isSetLdInst()).isFalse(); + assertThat(extRef.isSetPrefix()).isFalse(); + assertThat(extRef.isSetLnClass()).isFalse(); + assertThat(extRef.isSetLnInst()).isFalse(); + assertThat(extRef.isSetDoName()).isFalse(); + assertThat(extRef.isSetDaName()).isFalse(); + assertThat(extRef.isSetServiceType()).isFalse(); + assertThat(extRef.isSetSrcLDInst()).isFalse(); + assertThat(extRef.isSetPrefix()).isFalse(); + assertThat(extRef.isSetSrcLNClass()).isFalse(); + assertThat(extRef.isSetLnInst()).isFalse(); + assertThat(extRef.isSetSrcCBName()).isFalse(); + } + + private TExtRef findExtRef(SclReport sclReport, String nameOfIED, String lDeviceInst, String extRefDesc) { + return findLDeviceAdapter(sclReport, nameOfIED, lDeviceInst) + .getLN0Adapter() + .getCurrentElem() + .getInputs() + .getExtRef().stream().filter(extRef -> extRefDesc.equals(extRef.getDesc())) + .findFirst().orElseThrow( + () -> new AssertionFailedError(String.format("ExtRef.des=%s not found in IED.name=%s,LDevice.inst=%s", extRefDesc, lDeviceInst, nameOfIED))); + } + + private LDeviceAdapter findLDeviceAdapter(SclReport sclReport, String nameOfIED, String lDeviceInst) { + return sclReport.getSclRootAdapter() + .getIEDAdapterByName(nameOfIED) + .getLDeviceAdapterByLdInst(lDeviceInst) + .orElseThrow(() -> new AssertionFailedError(String.format("LDevice.inst=%s not found in IED.name=%s", lDeviceInst, nameOfIED))); + } + + @Test + void updateAllExtRefIedNames_when_lDevice_off_should_remove_binding() throws Exception { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml"); + // When + SclReport sclReport = ExtRefService.updateAllExtRefIedNames(scd); + // Then + assertThat(sclReport).isNotNull(); + LDeviceAdapter lDeviceAdapter = getLDeviceByLdName("IED_NAME1LD_INST12", sclReport.getSclRootAdapter()); + assertThat(lDeviceAdapter.getLDeviceStatus()).hasValue("off"); + assertThat(lDeviceAdapter.getLN0Adapter().getInputsAdapter().getCurrentElem().getExtRef()) + .allSatisfy(this::assertExtRefIsNotBound); + } + + @Test + void updateAllExtRefIedNames_when_FlowStatus_INACTIVE_should_remove_binding() throws Exception { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml"); + // When + SclReport sclReport = ExtRefService.updateAllExtRefIedNames(scd); + // Then + assertThat(sclReport).isNotNull(); + LDeviceAdapter lDeviceAdapter = getLDeviceByLdName("IED_NAME1LD_INST11", sclReport.getSclRootAdapter()); + assertThat(lDeviceAdapter.getLDeviceStatus()).hasValue("on"); + Optional optionalTExtRef = lDeviceAdapter.getCurrentElem().getLN0().getInputs().getExtRef().stream() + .filter(tExtRef -> "Match compas:Flow but FlowStatus is INACTIVE".equals(tExtRef.getDesc())) + .findFirst(); + assertThat(optionalTExtRef).isPresent(); + TExtRef extRef = optionalTExtRef.get(); + assertExtRefIsNotBound(extRef); + } + + private void assertExtRefIsNotBound(TExtRef extRef) { + assertThat(extRef.isSetIedName()).isFalse(); + assertThat(extRef.isSetLdInst()).isFalse(); + assertThat(extRef.isSetPrefix()).isFalse(); + assertThat(extRef.isSetLnClass()).isFalse(); + assertThat(extRef.isSetLnInst()).isFalse(); + assertThat(extRef.isSetDoName()).isFalse(); + assertThat(extRef.isSetDaName()).isFalse(); + assertThat(extRef.isSetServiceType()).isFalse(); + assertThat(extRef.isSetSrcLDInst()).isFalse(); + assertThat(extRef.isSetSrcPrefix()).isFalse(); + assertThat(extRef.isSetSrcLNClass()).isFalse(); + assertThat(extRef.isSetSrcLNInst()).isFalse(); + assertThat(extRef.isSetSrcCBName()).isFalse(); + } + + private LDeviceAdapter getLDeviceByLdName(String ldName, SclRootAdapter sclRootAdapter) { + Optional optionalLDeviceAdapter = sclRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters) + .filter(lDeviceAdapter -> ldName.equals(lDeviceAdapter.getLdName())) + .findFirst(); + assertThat(optionalLDeviceAdapter).isPresent(); + return optionalLDeviceAdapter.get(); + } + +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/PrivateServiceTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/PrivateServiceTest.java index e3213f04d..9d55cc596 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/PrivateServiceTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/PrivateServiceTest.java @@ -56,10 +56,10 @@ void class_should_not_be_instantiable() { } @Test - void getCompasPrivates_should_return_privates_value() { + void extractCompasPrivates_should_return_privates_value() { // Given : setUp // When - List result = PrivateService.getCompasPrivates(List.of(privateSCD, privateICD), + List result = PrivateService.extractCompasPrivates(List.of(privateSCD, privateICD), TCompasSclFileType.class); //Then assertThat(result) @@ -68,42 +68,42 @@ void getCompasPrivates_should_return_privates_value() { } @Test - void getCompasPrivates_when_no_privates_match_class_should_return_empty_list() { + void extractCompasPrivates_when_no_privates_match_class_should_return_empty_list() { // Given : setUp // When - List result = PrivateService.getCompasPrivates(List.of(privateSCD), TCompasICDHeader.class); + List result = PrivateService.extractCompasPrivates(List.of(privateSCD), TCompasICDHeader.class); //Then assertThat(result).isEmpty(); } @Test - void getCompasPrivates_when_class_is_not_compas_class_should_throw_exception() { + void extractCompasPrivates_when_class_is_not_compas_class_should_throw_exception() { // Given : setUp List privates = List.of(privateSCD); // When & Then - assertThatThrownBy(() -> PrivateService.getCompasPrivates(privates, Object.class)).isInstanceOf( + assertThatThrownBy(() -> PrivateService.extractCompasPrivates(privates, Object.class)).isInstanceOf( NoSuchElementException.class); } @Test - void getCompasPrivates_when_content_not_match_private_type_should_throw_exception() { + void extractCompasPrivates_when_content_not_match_private_type_should_throw_exception() { // Given : setUp privateSCD.setType(PrivateEnum.COMPAS_BAY.getPrivateType()); Class compasClass = PrivateEnum.COMPAS_BAY.getCompasClass(); List privates = List.of(privateSCD); // When & Then - assertThatThrownBy(() -> PrivateService.getCompasPrivates(privates, compasClass)).isInstanceOf( + assertThatThrownBy(() -> PrivateService.extractCompasPrivates(privates, compasClass)).isInstanceOf( ScdException.class); } @Test - void getCompasPrivates_on_base_element_should_return_privates_value() { + void extractCompasPrivates_on_base_element_should_return_privates_value() { // Given : setUp TBaseElement baseElement = new SCL(); baseElement.getPrivate().add(privateSCD); baseElement.getPrivate().add(privateICD); // When - List result = PrivateService.getCompasPrivates(baseElement, TCompasSclFileType.class); + List result = PrivateService.extractCompasPrivates(baseElement, TCompasSclFileType.class); // Then assertThat(result) .hasSize(2) @@ -111,20 +111,20 @@ void getCompasPrivates_on_base_element_should_return_privates_value() { } @Test - void getCompasPrivates_on_base_element_should_not_set_private() { + void extractCompasPrivates_on_base_element_should_not_set_private() { // Given TBaseElement baseElement = new SCL(); // When - PrivateService.getCompasPrivates(baseElement, TCompasSclFileType.class); + PrivateService.extractCompasPrivates(baseElement, TCompasSclFileType.class); // Then assertThat(baseElement.isSetPrivate()).isFalse(); } @Test - void getCompasPrivate_should_return_private_value() { + void extractCompasPrivate_should_return_private_value() { // Given : setUp // When - Optional result = PrivateService.getCompasPrivate(privateSCD, + Optional result = PrivateService.extractCompasPrivate(privateSCD, TCompasSclFileType.class); //Then assertThat(result).isPresent() @@ -132,34 +132,69 @@ void getCompasPrivate_should_return_private_value() { } @Test - void getCompasPrivate_should_return_empty() { + void extractCompasPrivate_should_return_empty() { // Given : setUp // When - Optional result = PrivateService.getCompasPrivate(privateSCD, + Optional result = PrivateService.extractCompasPrivate(privateSCD, TCompasBay.class); //Then assertThat(result).isNotPresent(); } @Test - void getCompasPrivate_should_throw_exception() { + void extractCompasPrivate_should_throw_exception() { // Given : setUp privateSCD.getContent().add(objectFactory.createSclFileType(TCompasSclFileType.ICD)); Class compasClass = PrivateEnum.COMPAS_SCL_FILE_TYPE.getCompasClass(); // When & Then - assertThatThrownBy(() -> PrivateService.getCompasPrivate(privateSCD, compasClass)).isInstanceOf( + assertThatThrownBy(() -> PrivateService.extractCompasPrivate(privateSCD, compasClass)).isInstanceOf( ScdException.class); } @Test - void getCompasICDHeader_should_return_private_value() { + void extractCompasPrivate_on_base_element_should_return_private_value() { + // Given : setUp + TBaseElement baseElement = new SCL(); + baseElement.getPrivate().add(privateSCD); + // When + Optional result = PrivateService.extractCompasPrivate(baseElement, + TCompasSclFileType.class); + //Then + assertThat(result).isPresent() + .hasValue(TCompasSclFileType.SCD); + } + + @Test + void extractCompasPrivate_on_base_element_should_return_empty() { + // Given + TBaseElement baseElement = new SCL(); + // When + Optional result = PrivateService.extractCompasPrivate(baseElement, + TCompasBay.class); + //Then + assertThat(result).isNotPresent(); + } + + @Test + void extractCompasPrivate_on_base_element_should_throw_exception() { + // Given : setUp + TBaseElement baseElement = new SCL(); + baseElement.getPrivate().add(privateSCD); + baseElement.getPrivate().add(privateICD); + // When & Then + assertThatThrownBy(() -> PrivateService.extractCompasPrivate(baseElement, TCompasSclFileType.class)).isInstanceOf( + ScdException.class); + } + + @Test + void extractCompasICDHeader_should_return_private_value() { // Given privateSCD = objectFactory.createTPrivate(); privateSCD.setType(PrivateEnum.COMPAS_ICDHEADER.getPrivateType()); TCompasICDHeader tCompasICDHeader = objectFactory.createTCompasICDHeader(); privateSCD.getContent().add(objectFactory.createICDHeader(tCompasICDHeader)); // When - Optional optionalResult = PrivateService.getCompasICDHeader(privateSCD); + Optional optionalResult = PrivateService.extractCompasICDHeader(privateSCD); //Then assertThat(optionalResult).isPresent().get().matches(result -> result == tCompasICDHeader); } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapterTest.java index f83ab071b..0248ccdfc 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapterTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/SclRootAdapterTest.java @@ -4,7 +4,6 @@ package org.lfenergy.compas.sct.commons.scl; -import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.lfenergy.compas.scl2007b4.model.SCL; import org.lfenergy.compas.scl2007b4.model.TPrivate; @@ -16,7 +15,6 @@ import static org.junit.jupiter.api.Assertions.*; import static org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller.assertIsMarshallable; -@Slf4j class SclRootAdapterTest { 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 6133cd298..f5984077b 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 @@ -21,7 +21,7 @@ import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDa; import static org.lfenergy.compas.sct.commons.testhelpers.DataTypeUtils.createDo; @@ -181,7 +181,7 @@ void testGetExtRefBinders() throws Exception { "Do11.sdo11", "da11.bda111.bda112.bda113", "INT_ADDR11" ); - List potentialBinders = assertDoesNotThrow( + assertDoesNotThrow( () -> SclService.getExtRefBinders( scd, "IED_NAME1", "LD_INST11", "LLN0", "", "", signalInfo ) @@ -195,6 +195,34 @@ void testGetExtRefBinders() throws Exception { ); } + @Test + void test_getExtRefBinders_should_return_sorted_list() 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" + ); + + // 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) + .extracting(ExtRefBindingInfo::getIedName) + .containsExactly("IED_NAME1"); + assertThat(potentialBinders) + .extracting(ExtRefBindingInfo::getLdInst) + .containsExactly("LD_INST12"); + assertThat(potentialBinders) + .extracting(ExtRefBindingInfo::getLnClass) + .containsExactly("LLN0"); + assertThat(potentialBinders) + .extracting(ExtRefBindingInfo::getLnInst) + .containsExactly(""); + } + @Test void testUpdateExtRefBinders() throws Exception { SclRootAdapter sclRootAdapter = new SclRootAdapter("hId", SclRootAdapter.VERSION, SclRootAdapter.REVISION); @@ -245,7 +273,8 @@ void testUpdateExtRefBinders() throws Exception { } @Test - void testGetExtRefSourceInfo() throws Exception { + void getExtRefSourceInfo_shouldReturnEmptyList_whenExtRefMatchNoFCDA() throws Exception { + //Given SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); String iedName = "IED_NAME2"; String ldInst = "LD_INST21"; @@ -263,49 +292,129 @@ void testGetExtRefSourceInfo() throws Exception { extRefInfo.setHolderLDInst(ldInst); extRefInfo.setHolderLnClass(lnClass); - var controlBlocks = SclService.getExtRefSourceInfo(scd, extRefInfo); - assertEquals(2, controlBlocks.size()); - controlBlocks.forEach(controlBlock -> assertTrue( - controlBlock.getName().equals("goose1") || controlBlock.getName().equals("smv1") - ) - ); + //When + List> controlBlocks = SclService.getExtRefSourceInfo(scd, extRefInfo); + + //Then + assertThat(controlBlocks).hasSize(0); } @Test - void testUpdateExtRefSource() throws Exception { + void getExtRefSourceInfo_shouldReturnListOfControlBlocks_whenExtRefMatchFCDA() throws Exception { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/issue_175_scd_get_cbs_test.xml"); + String iedName = "IED_NAME2"; + String ldInst = "LD_INST21"; + String lnClass = TLLN0Enum.LLN_0.value(); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(() -> iedAdapter.getLDeviceAdapterByLdInst(ldInst).get()); + LN0Adapter ln0Adapter = lDeviceAdapter.getLN0Adapter(); + List extRefs = ln0Adapter.getExtRefs(null); + assertFalse(extRefs.isEmpty()); + + ExtRefInfo extRefInfo = new ExtRefInfo(extRefs.get(0)); + + extRefInfo.setHolderIEDName(iedName); + extRefInfo.setHolderLDInst(ldInst); + extRefInfo.setHolderLnClass(lnClass); + + //When + List> controlBlocks = SclService.getExtRefSourceInfo(scd, extRefInfo); + + //Then + assertThat(controlBlocks).hasSize(1); + assertThat(controlBlocks.get(0).getName()).isEqualTo("goose2"); + } + + @Test + void updateExtRefSource_shouldThrowScdException_whenSignalInfoNullOrInvalid() throws Exception { + //Given SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); ExtRefInfo extRefInfo = new ExtRefInfo(); extRefInfo.setHolderIEDName("IED_NAME2"); extRefInfo.setHolderLDInst("LD_INST21"); extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // signal = null + //When Then + assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // signal = null extRefInfo.setSignalInfo(new ExtRefSignalInfo()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // signal invalid + assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class);// signal invalid + } - extRefInfo.getSignalInfo().setIntAddr("INT_ADDR21"); - extRefInfo.getSignalInfo().setPDA("da21.bda211.bda212.bda213"); - extRefInfo.getSignalInfo().setPDO("Do21.sdo21"); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // binding = null + @Test + void updateExtRefSource_shouldThrowScdException_whenBindingInfoNullOrInvalid() throws Exception { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setHolderIEDName("IED_NAME2"); + extRefInfo.setHolderLDInst("LD_INST21"); + extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); + + ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); + extRefSignalInfo.setIntAddr("INT_ADDR21"); + extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); + extRefSignalInfo.setPDO("Do21.sdo21"); + extRefInfo.setSignalInfo(extRefSignalInfo); + //When Then + assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // binding = null extRefInfo.setBindingInfo(new ExtRefBindingInfo()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // binding invalid + assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class);// binding invalid + } + @Test + void updateExtRefSource_shouldThrowScdException_whenBindingInternalBinding() throws Exception { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setHolderIEDName("IED_NAME2"); + extRefInfo.setHolderLDInst("LD_INST21"); + extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); + + ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); + extRefSignalInfo.setIntAddr("INT_ADDR21"); + extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); + extRefSignalInfo.setPDO("Do21.sdo21"); + extRefInfo.setSignalInfo(extRefSignalInfo); + + ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); + extRefBindingInfo.setIedName("IED_NAME2"); // internal binding + extRefBindingInfo.setLdInst("LD_INST12"); + extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); + extRefInfo.setBindingInfo(new ExtRefBindingInfo()); + //When Then + assertThatThrownBy(() -> SclService.updateExtRefSource(scd, extRefInfo)).isInstanceOf(ScdException.class); // CB not allowed + } + @Test + void updateExtRefSource_shouldThrowScdException_whenBindingExternalBinding() throws Exception { + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scl-srv-scd-extref-cb/scd_get_cbs_test.xml"); + ExtRefInfo extRefInfo = new ExtRefInfo(); + extRefInfo.setHolderIEDName("IED_NAME2"); + extRefInfo.setHolderLDInst("LD_INST21"); + extRefInfo.setHolderLnClass(TLLN0Enum.LLN_0.value()); - extRefInfo.getBindingInfo().setIedName("IED_NAME2"); // internal binding - extRefInfo.getBindingInfo().setLdInst("LD_INST12"); - extRefInfo.getBindingInfo().setLnClass(TLLN0Enum.LLN_0.value()); - assertThrows(ScdException.class, () -> SclService.updateExtRefSource(scd, extRefInfo)); // CB not allowed + ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(); + extRefSignalInfo.setIntAddr("INT_ADDR21"); + extRefSignalInfo.setPDA("da21.bda211.bda212.bda213"); + extRefSignalInfo.setPDO("Do21.sdo21"); + extRefInfo.setSignalInfo(extRefSignalInfo); - extRefInfo.getBindingInfo().setIedName("IED_NAME1"); + ExtRefBindingInfo extRefBindingInfo = new ExtRefBindingInfo(); + extRefBindingInfo.setIedName("IED_NAME1"); + extRefBindingInfo.setLdInst("LD_INST12"); + extRefBindingInfo.setLnClass(TLLN0Enum.LLN_0.value()); + extRefInfo.setBindingInfo(extRefBindingInfo); extRefInfo.setSourceInfo(new ExtRefSourceInfo()); extRefInfo.getSourceInfo().setSrcLDInst(extRefInfo.getBindingInfo().getLdInst()); extRefInfo.getSourceInfo().setSrcLNClass(extRefInfo.getBindingInfo().getLnClass()); extRefInfo.getSourceInfo().setSrcCBName("goose1"); + + //When Then TExtRef extRef = assertDoesNotThrow(() -> SclService.updateExtRefSource(scd, extRefInfo)); assertEquals(extRefInfo.getSourceInfo().getSrcCBName(), extRef.getSrcCBName()); } - private ExtRefSignalInfo createSignalInfo(String pDO, String pDA, String intAddr) { final String DESC = "DESC"; @@ -651,8 +760,7 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_D SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); // Then SclRootAdapter scdRootAdapter = new SclRootAdapter(scl); - List lDevices = scdRootAdapter.getIEDAdapters().stream().map(IEDAdapter::getLDeviceAdapters) - .flatMap(List::stream).collect(Collectors.toList()); + List lDevices = scdRootAdapter.streamIEDAdapters().flatMap(IEDAdapter::streamLDeviceAdapters).collect(Collectors.toList()); List ln0s = lDevices.stream().map(LDeviceAdapter::getLN0Adapter).map(LN0Adapter::getCurrentElem).collect(Collectors.toList()); assertThat(ln0s) .isNotEmpty() @@ -672,9 +780,9 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_controlBlocks_and_D SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scl); // Then SclRootAdapter scdRootAdapter = new SclRootAdapter(scl); - List lDevices = scdRootAdapter.getIEDAdapters().stream().map(IEDAdapter::getLDeviceAdapters) - .flatMap(List::stream).collect(Collectors.toList()); - List lns = lDevices.stream().map(LDeviceAdapter::getLNAdapters).flatMap(List::stream) + List lns = scdRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters) + .map(LDeviceAdapter::getLNAdapters).flatMap(List::stream) .map(LNAdapter::getCurrentElem).collect(Collectors.toList()); assertThat(lns) .isNotEmpty() @@ -693,8 +801,8 @@ void removeControlBlocksAndDatasetAndExtRefSrc_should_remove_srcXXX_attributes_o // Then SclRootAdapter scdRootAdapter = new SclRootAdapter(scl); List extRefs = scdRootAdapter - .getIEDAdapters().stream() - .map(IEDAdapter::getLDeviceAdapters).flatMap(List::stream) + .streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters) .map(LDeviceAdapter::getLN0Adapter) .map(AbstractLNAdapter::getExtRefs).flatMap(List::stream) .collect(Collectors.toList()); @@ -714,13 +822,13 @@ private static Stream sclProviderMissingRequiredObjects() throws Exce SCL scl3 = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_KO_MissingLDevicePrivateAttribute.scd"); SCL scl4 = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_KO_MissingMod.scd"); Tuple[] scl1Errors = new Tuple[]{Tuple.tuple("The LDevice doesn't have a DO @name='Beh' OR its associated DA@fc='ST' AND DA@name='stVal'", - "/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType1\"]")}; + "/SCL/IED[@name=\"IedName1\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0")}; Tuple[] scl2Errors = new Tuple[]{Tuple.tuple("The LDevice doesn't have a Private compas:LDevice.", - "/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType1\"]")}; + "/SCL/IED[@name=\"IedName1\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0")}; Tuple[] scl3Errors = new Tuple[]{Tuple.tuple("The Private compas:LDevice doesn't have the attribute 'LDeviceStatus'", - "/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType1\"]")}; + "/SCL/IED[@name=\"IedName1\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0")}; Tuple[] scl4Errors = new Tuple[]{Tuple.tuple("The LDevice doesn't have a DO @name='Mod'", - "/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType1\"]")}; + "/SCL/IED[@name=\"IedName1\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0")}; return Stream.of( Arguments.of("MissingDOBeh",scl1, scl1Errors), Arguments.of("MissingLDevicePrivate",scl2, scl2Errors), @@ -741,9 +849,9 @@ void updateLDeviceStatus_shouldReturnReportWithError_MissingRequiredObject(Strin // Then String after = createWrapper().marshall(sclReport.getSclRootAdapter().getCurrentElem()); assertFalse(sclReport.isSuccess()); - assertThat(sclReport.getErrorDescriptionList()) + assertThat(sclReport.getSclReportItems()) .hasSize(1) - .extracting(SclReport.ErrorDescription::getMessage, SclReport.ErrorDescription::getXpath) + .extracting(SclReportItem::getMessage, SclReportItem::getXpath) .containsExactly(errors); assertEquals("off", getLDeviceStatusValue(sclReport.getSclRootAdapter().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); assertEquals(before, after); @@ -754,25 +862,25 @@ private static Stream sclProviderBasedLDeviceStatus() throws Exceptio SCL scl2 = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_LD_STATUS_UNTESTED.scd"); SCL scl3 = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test1_LD_STATUS_INACTIVE.scd"); Tuple[] scl1Errors = new Tuple[]{Tuple.tuple("The LDevice cannot be set to 'off' but has not been selected into SSD.", - "/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType1\"]"), + "/SCL/IED[@name=\"IedName1\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0"), Tuple.tuple("The LDevice cannot be set to 'on' but has been selected into SSD.", - "/SCL/IED[@name=\"IedName2\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType2\"]"), + "/SCL/IED[@name=\"IedName2\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0"), Tuple.tuple("The LDevice cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'.", - "/SCL/IED[@name=\"IedName3\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType3\"]" + "/SCL/IED[@name=\"IedName3\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0" )}; Tuple[] scl2Errors = new Tuple[]{Tuple.tuple("The LDevice cannot be set to 'off' but has not been selected into SSD.", - "/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType1\"]"), + "/SCL/IED[@name=\"IedName1\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0"), Tuple.tuple("The LDevice cannot be set to 'on' but has been selected into SSD.", - "/SCL/IED[@name=\"IedName2\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType2\"]"), + "/SCL/IED[@name=\"IedName2\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0"), Tuple.tuple("The LDevice cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'.", - "/SCL/IED[@name=\"IedName3\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType3\"]" + "/SCL/IED[@name=\"IedName3\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0" )}; Tuple[] scl3Errors = new Tuple[]{Tuple.tuple("The LDevice is not qualified into STD but has been selected into SSD.", - "/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType1\"]"), + "/SCL/IED[@name=\"IedName1\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0"), Tuple.tuple("The LDevice cannot be set to 'on' but has been selected into SSD.", - "/SCL/IED[@name=\"IedName2\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType2\"]"), + "/SCL/IED[@name=\"IedName2\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0"), Tuple.tuple("The LDevice cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'.", - "/SCL/IED[@name=\"IedName3\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType3\"]" + "/SCL/IED[@name=\"IedName3\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0" )}; return Stream.of( Arguments.of("ACTIVE", scl1, scl1Errors), @@ -794,9 +902,9 @@ void updateLDeviceStatus_shouldReturnReportWithError_WhenLDeviceStatusActiveOrUn // Then String after = createWrapper().marshall(sclReport.getSclRootAdapter().getCurrentElem()); assertFalse(sclReport.isSuccess()); - assertThat(sclReport.getErrorDescriptionList()) + assertThat(sclReport.getSclReportItems()) .hasSize(3) - .extracting(SclReport.ErrorDescription::getMessage, SclReport.ErrorDescription::getXpath) + .extracting(SclReportItem::getMessage, SclReportItem::getXpath) .containsExactly(errors); assertEquals("off", getLDeviceStatusValue(sclReport.getSclRootAdapter().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); assertEquals("on", getLDeviceStatusValue(sclReport.getSclRootAdapter().getCurrentElem(), "IedName2", "LDSUIED").get().getValue()); @@ -815,13 +923,13 @@ void updateLDeviceStatus_shouldReturnReportWithError_WhenAllLDeviceInactive_Test SclReport sclReport = SclService.updateLDeviceStatus(scl); // Then assertFalse(sclReport.isSuccess()); - assertThat(sclReport.getErrorDescriptionList()) + assertThat(sclReport.getSclReportItems()) .hasSize(2) - .extracting(SclReport.ErrorDescription::getMessage, SclReport.ErrorDescription::getXpath) + .extracting(SclReportItem::getMessage, SclReportItem::getXpath) .containsExactly(Tuple.tuple("The LDevice cannot be set to 'off' but has not been selected into SSD.", - "/SCL/IED[@name=\"IedName1\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType1\"]"), + "/SCL/IED[@name=\"IedName1\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0"), Tuple.tuple("The LDevice is not qualified into STD but has been selected into SSD.", - "/SCL/IED[@name=\"IedName2\"]/LDevice[@inst=\"LDSUIED\"]/LN[lnClass=\"LLN0\" and @inst=\"\" and @lnType=\"LNType2\"]")); + "/SCL/IED[@name=\"IedName2\"]/AccessPoint/Server/LDevice[@inst=\"LDSUIED\"]/LN0")); assertEquals("off", getLDeviceStatusValue(sclReport.getSclRootAdapter().getCurrentElem(), "IedName1", "LDSUIED").get().getValue()); assertEquals("on", getLDeviceStatusValue(sclReport.getSclRootAdapter().getCurrentElem(), "IedName2", "LDSUIED").get().getValue()); assertTrue(getLDeviceStatusValue(scl, "IedName3", "LDSUIED").isPresent()); @@ -855,24 +963,6 @@ void updateLDeviceStatus_shouldReturnUpdatedFile() throws Exception { assertEquals("off", getLDeviceStatusValue(sclReport.getSclRootAdapter().getCurrentElem(), "IedName3", "LDSUIED").get().getValue()); } - @Test - void updateLDeviceStatus_shouldReturnError_when_DaiNotUpdatable() throws Exception { - // Given - SCL givenScl = SclTestMarshaller.getSCLFromFile("/scd-refresh-lnode/issue68_Test_Dai_Not_Updatable.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 - // Then - assertThatCode(() -> SclService.updateLDeviceStatus(givenScl)) - .isInstanceOf(ScdException.class) - .hasMessage("DAI (Mod -stVal) cannot be updated"); - } - - private Optional getLDeviceStatusValue(SCL scl, String iedName, String ldInst){ SclRootAdapter sclRootAdapter = new SclRootAdapter(scl); IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(iedName); 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 3f6fa1ad2..2671ba77b 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 @@ -5,18 +5,13 @@ package org.lfenergy.compas.sct.commons.scl.ied; import org.junit.jupiter.api.Test; -import org.lfenergy.compas.scl2007b4.model.LN0; -import org.lfenergy.compas.scl2007b4.model.SCL; -import org.lfenergy.compas.scl2007b4.model.TLLN0Enum; -import org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum; -import org.lfenergy.compas.scl2007b4.model.TPredefinedCDCEnum; +import org.lfenergy.compas.scl2007b4.model.*; import org.lfenergy.compas.sct.commons.dto.DaTypeName; import org.lfenergy.compas.sct.commons.dto.DoTypeName; import org.lfenergy.compas.sct.commons.exception.ScdException; 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 { @@ -178,4 +173,4 @@ void testGetDaiNumericValue() { assertDoesNotThrow(()->daiTracker.getDaiNumericValue(daTypeName,13.0)); } -} \ No newline at end of file +} 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 cd9277ef4..3d828c3a0 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,13 +13,13 @@ 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; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; @@ -53,13 +53,16 @@ void testAmChildElementRef() throws ScdException { } - @Test - void testGetLDeviceAdapters() throws Exception { + void streamLDeviceAdapters_should_return_all_lDevices() throws Exception { + // Given SCL scd = SclTestMarshaller.getSCLFromFile(SCD_IED_U_TEST); SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); - IEDAdapter iAdapter = assertDoesNotThrow( () -> sclRootAdapter.getIEDAdapterByName("IED_NAME")); - assertFalse(iAdapter.getLDeviceAdapters().isEmpty()); + IEDAdapter iAdapter = sclRootAdapter.getIEDAdapterByName("IED_NAME"); + // When + Stream result = iAdapter.streamLDeviceAdapters(); + // Then + assertThat(result).hasSize(3); } @Test @@ -77,13 +80,13 @@ void testUpdateLDeviceNodesType() throws Exception { SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iAdapter = assertDoesNotThrow( () -> sclRootAdapter.getIEDAdapterByName(DTO.HOLDER_IED_NAME)); - assertTrue(iAdapter.getLDeviceAdapters().size() >= 2); + assertTrue(iAdapter.streamLDeviceAdapters().count() >= 2); Map pairOldNewId = new HashMap<>(); pairOldNewId.put("LNO1", DTO.HOLDER_IED_NAME + "_LNO1"); pairOldNewId.put("LNO2", DTO.HOLDER_IED_NAME + "_LNO2"); assertDoesNotThrow( () ->iAdapter.updateLDeviceNodesType(pairOldNewId)); - LDeviceAdapter lDeviceAdapter = iAdapter.getLDeviceAdapters().get(0); + LDeviceAdapter lDeviceAdapter = iAdapter.streamLDeviceAdapters().findFirst().get(); assertEquals(DTO.HOLDER_IED_NAME + "_LNO1",lDeviceAdapter.getLN0Adapter().getLnType()); } diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapterTest.java new file mode 100644 index 000000000..79bb064d7 --- /dev/null +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/InputsAdapterTest.java @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2022 RTE FRANCE +// +// SPDX-License-Identifier: Apache-2.0 + +package org.lfenergy.compas.sct.commons.scl.ied; + +import org.junit.jupiter.api.Test; +import org.lfenergy.compas.scl2007b4.model.LN0; +import org.lfenergy.compas.scl2007b4.model.TInputs; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatNoException; + +class InputsAdapterTest { + + @Test + void constructor_should_succeed() { + // Given + TInputs tInputs = new TInputs(); + LN0 ln0 = new LN0(); + ln0.setInputs(tInputs); + LN0Adapter ln0Adapter = new LN0Adapter(null, ln0); + // When && Then + assertThatNoException().isThrownBy(() -> new InputsAdapter(ln0Adapter, tInputs)); + } + + @Test + void elementXPath_should_succeed() { + // Given + TInputs tInputs = new TInputs(); + InputsAdapter inputsAdapter = new InputsAdapter(null, tInputs); + // When + String result = inputsAdapter.elementXPath(); + // Then + assertThat(result).isEqualTo("Inputs"); + } + +} 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 4c5f893cb..86b0d045d 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 @@ -21,6 +21,7 @@ import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller; import java.util.List; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; @@ -117,6 +118,39 @@ void elementXPath(String ldInst, String message) { String elementXPathResult = lDeviceAdapter.elementXPath(); // Then assertThat(elementXPathResult).isEqualTo(message); + } + + @Test + void getLDeviceStatus_should_succeed() throws Exception { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml"); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + Optional optionalLDeviceAdapter = sclRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters) + .filter(lDeviceAdapter -> "IED_NAME1LD_INST13".equals(lDeviceAdapter.getLdName())) + .findFirst(); + assertThat(optionalLDeviceAdapter).isPresent(); + LDeviceAdapter lDeviceAdapter = optionalLDeviceAdapter.get(); + // When + Optional result = lDeviceAdapter.getLDeviceStatus(); + // Then + assertThat(result) + .isPresent() + .hasValue("test"); + } + + @Test + void getLNAdaptersInclundigLN0() { + //Given + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(()-> iAdapter.getLDeviceAdapterByLdInst("LD_INS2").get()); + //When + List> lnAdapters = lDeviceAdapter.getLNAdaptersInclundigLN0(); + //Then + assertThat(lnAdapters) + .hasSize(2) + .hasAtLeastOneElementOfType(LN0Adapter.class) + .hasAtLeastOneElementOfType(LNAdapter.class); } -} \ No newline at end of file +} + diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LN0AdapterTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/scl/ied/LN0AdapterTest.java index b0387c69c..6b980c956 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.Optional; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; @@ -393,6 +394,26 @@ void elementXPath() { // When String result = lnAdapter.elementXPath(); // Then - assertThat(result).isEqualTo("LN[lnClass=\"LLN0\" and not(@inst) and not(@lnType)]"); + assertThat(result).isEqualTo("LN0"); + } + + @Test + void getLDeviceStatus_should_succeed() throws Exception { + // Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml"); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + Optional optionalLN0Adapter = sclRootAdapter.streamIEDAdapters() + .flatMap(IEDAdapter::streamLDeviceAdapters) + .filter(lDeviceAdapter -> "IED_NAME1LD_INST13".equals(lDeviceAdapter.getLdName())) + .map(LDeviceAdapter::getLN0Adapter) + .findFirst(); + assertThat(optionalLN0Adapter).isPresent(); + LN0Adapter ln0Adapter = optionalLN0Adapter.get(); + // When + Optional result = ln0Adapter.getLDeviceStatus(); + // Then + assertThat(result) + .isPresent() + .hasValue("test"); } } 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 e5f38aaee..64d0f02af 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 @@ -5,6 +5,9 @@ package org.lfenergy.compas.sct.commons.scl.ied; import org.junit.jupiter.api.Test; +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; @@ -15,8 +18,10 @@ import org.mockito.Mockito; import java.util.List; +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.*; class LNAdapterTest { @@ -26,26 +31,26 @@ void testAmChildElementRef() { TLN tln = new TLN(); LNAdapter lnAdapter = initLNAdapter(tln); - assertEquals(TLN.class,lnAdapter.getElementClassType()); - assertEquals(DTO.LN_TYPE,lnAdapter.getLnType()); - assertEquals(DTO.HOLDER_LN_CLASS,lnAdapter.getLNClass()); + assertEquals(TLN.class, lnAdapter.getElementClassType()); + assertEquals(DTO.LN_TYPE, lnAdapter.getLnType()); + assertEquals(DTO.HOLDER_LN_CLASS, lnAdapter.getLNClass()); assertFalse(lnAdapter.hasInputs()); tln.setInputs(new TInputs()); assertTrue(lnAdapter.hasInputs()); assertFalse(lnAdapter.isLN0()); - assertEquals(DTO.HOLDER_LN_INST,lnAdapter.getLNInst()); - assertEquals(DTO.HOLDER_LN_PREFIX,lnAdapter.getPrefix()); + assertEquals(DTO.HOLDER_LN_INST, lnAdapter.getLNInst()); + assertEquals(DTO.HOLDER_LN_PREFIX, lnAdapter.getPrefix()); assertTrue(lnAdapter.getCurrentElem().getReportControl().isEmpty()); assertDoesNotThrow(() -> lnAdapter.addControlBlock(new ReportControlBlock())); assertFalse(lnAdapter.getCurrentElem().getReportControl().isEmpty()); - assertThrows(IllegalArgumentException.class, () -> new LNAdapter(lnAdapter.getParentAdapter(), new TLN())); + assertThrows(IllegalArgumentException.class, () -> new LNAdapter(lnAdapter.getParentAdapter(), new TLN())); } @Test - void testGetExtRefs(){ + void testGetExtRefs() { TLN tln = new TLN(); LNAdapter lnAdapter = initLNAdapter(tln); @@ -55,12 +60,12 @@ void testGetExtRefs(){ ExtRefSignalInfo extRefSignalInfo = new ExtRefSignalInfo(extRef); tInputs.getExtRef().add(DTO.createExtRef()); tln.setInputs(tInputs); - assertEquals(1,lnAdapter.getExtRefs(null).size()); - assertEquals(1,lnAdapter.getExtRefs(extRefSignalInfo).size()); + assertEquals(1, lnAdapter.getExtRefs(null).size()); + assertEquals(1, lnAdapter.getExtRefs(extRefSignalInfo).size()); } @Test - void testFindDataSetByRef(){ + void testFindDataSetByRef() { TLN tln = new TLN(); LNAdapter lnAdapter = initLNAdapter(tln); @@ -82,16 +87,16 @@ void testUpdateExtRefBinders() { 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()); + 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()); - lnAdapter.updateExtRefBindingInfo(extRef,extRefInfo); + lnAdapter.updateExtRefBindingInfo(extRef, extRefInfo); assertNull(extRef.getIedName()); assertNull(extRef.getSrcLDInst()); } @@ -118,10 +123,10 @@ void testUpdateExtRefBindingInfo() throws Exception { info.getSignalInfo().setPServT(null); assertDoesNotThrow(() -> lnAdapter.updateExtRefBinders(info)); List tExtRefs = lnAdapter.getExtRefs(null); - assertEquals(1,tExtRefs.size()); + assertEquals(1, tExtRefs.size()); TExtRef extRef = tExtRefs.get(0); - assertEquals(info.getBindingInfo().getIedName(),extRef.getIedName()); + assertEquals(info.getBindingInfo().getIedName(), extRef.getIedName()); } @@ -137,13 +142,13 @@ void checkExtRefInfoCoherence() throws Exception { .withLnClass(TLLN0Enum.LLN_0.value()) .build(); - assertThrows(IllegalArgumentException.class, () ->lnAdapter.checkExtRefInfoCoherence(new ExtRefInfo())); + assertThrows(IllegalArgumentException.class, () -> lnAdapter.checkExtRefInfoCoherence(new ExtRefInfo())); ExtRefInfo extRefInfo = DTO.createExtRefInfo(); extRefInfo.setBindingInfo(null); extRefInfo.setSourceInfo(null); - assertThrows(ScdException.class, () ->lnAdapter.checkExtRefInfoCoherence(extRefInfo)); + assertThrows(ScdException.class, () -> lnAdapter.checkExtRefInfoCoherence(extRefInfo)); extRefInfo.getSignalInfo().setDesc(null); extRefInfo.getSignalInfo().setPLN(null); @@ -152,12 +157,12 @@ void checkExtRefInfoCoherence() throws Exception { extRefInfo.getSignalInfo().setPDO("Do11.sdo11"); extRefInfo.getSignalInfo().setIntAddr("INT_ADDR11"); - TExtRef extRef = assertDoesNotThrow(() ->lnAdapter.checkExtRefInfoCoherence(extRefInfo)); - assertEquals(extRefInfo.getSignalInfo().getPDO(),extRef.getPDO()); + TExtRef extRef = assertDoesNotThrow(() -> lnAdapter.checkExtRefInfoCoherence(extRefInfo)); + assertEquals(extRefInfo.getSignalInfo().getPDO(), extRef.getPDO()); - ExtRefBindingInfo bindingInfo = DTO.createExtRefBindingInfo(); + ExtRefBindingInfo bindingInfo = DTO.createExtRefBindingInfo_Remote(); extRefInfo.setBindingInfo(bindingInfo); - assertThrows(ScdException.class, () ->lnAdapter.checkExtRefInfoCoherence(extRefInfo)); + assertThrows(ScdException.class, () -> lnAdapter.checkExtRefInfoCoherence(extRefInfo)); bindingInfo.setServiceType(null); bindingInfo.setIedName("IED_NAME1"); @@ -165,20 +170,61 @@ void checkExtRefInfoCoherence() throws Exception { bindingInfo.setLnInst("1"); bindingInfo.setLnClass("ANCR"); bindingInfo.setPrefix("PR"); - extRef = assertDoesNotThrow(() ->lnAdapter.checkExtRefInfoCoherence(extRefInfo)); - assertEquals(extRefInfo.getBindingInfo().getIedName(),extRef.getIedName()); + extRef = assertDoesNotThrow(() -> lnAdapter.checkExtRefInfoCoherence(extRefInfo)); + assertEquals(extRefInfo.getBindingInfo().getIedName(), extRef.getIedName()); ExtRefSourceInfo sourceInfo = new ExtRefSourceInfo(); sourceInfo.setSrcCBName("UNKNOWN_CB"); extRefInfo.setSourceInfo(sourceInfo); - assertThrows(ScdException.class, () ->lnAdapter.checkExtRefInfoCoherence(extRefInfo)); + assertThrows(ScdException.class, () -> lnAdapter.checkExtRefInfoCoherence(extRefInfo)); sourceInfo.setSrcCBName("rpt1"); - assertDoesNotThrow(() ->lnAdapter.checkExtRefInfoCoherence(extRefInfo)); + assertDoesNotThrow(() -> lnAdapter.checkExtRefInfoCoherence(extRefInfo)); + } + + @ParameterizedTest + @MethodSource("provideIncompleteExtRefInfo") + void should_throw_exception_when_trying_update_extRefSource_with_wrong_arguments(ExtRefInfo incompleteExtrefInfo) throws Exception { + + //Given + SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-cb/scd_get_cbs_test.xml"); + SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); + + IEDAdapter iAdapter = assertDoesNotThrow(() -> sclRootAdapter.getIEDAdapterByName("IED_NAME1")); + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(() -> iAdapter.getLDeviceAdapterByLdInst("LD_INST11").get()); + AbstractLNAdapter lnAdapter = AbstractLNAdapter.builder() + .withLDeviceAdapter(lDeviceAdapter) + .withLnClass(TLLN0Enum.LLN_0.value()) + .build(); + + //When Then + assertThatThrownBy(() -> lnAdapter.updateExtRefSource(incompleteExtrefInfo)) + .isInstanceOf(IllegalArgumentException.class); + + } + + private static Stream provideIncompleteExtRefInfo() { + + ExtRefInfo extRefInfoEmpty = new ExtRefInfo(); + + ExtRefInfo extRefInfoWithOnlySignalInfo = new ExtRefInfo(); + extRefInfoWithOnlySignalInfo.setSignalInfo(new ExtRefSignalInfo()); + + ExtRefInfo extRefInfoWithSignalInfoAndBindingInfo = new ExtRefInfo(); + extRefInfoWithSignalInfoAndBindingInfo.setSignalInfo(new ExtRefSignalInfo()); + extRefInfoWithSignalInfoAndBindingInfo.setBindingInfo(new ExtRefBindingInfo()); + + return Stream.of( + Arguments.of(extRefInfoEmpty), + Arguments.of(extRefInfoWithOnlySignalInfo), + Arguments.of(extRefInfoWithSignalInfoAndBindingInfo) + ); } @Test void testUpdateExtRefSource() throws Exception { + + //Given SCL scd = SclTestMarshaller.getSCLFromFile("/scd-extref-cb/scd_get_cbs_test.xml"); SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iAdapter = assertDoesNotThrow(() -> sclRootAdapter.getIEDAdapterByName("IED_NAME1")); @@ -187,13 +233,22 @@ void testUpdateExtRefSource() throws Exception { .withLDeviceAdapter(lDeviceAdapter) .withLnClass(TLLN0Enum.LLN_0.value()) .build(); + ExtRefInfo extRefInfo = givenCompleteExtRefInfo(); + + //When + TExtRef extRef = assertDoesNotThrow(() -> lnAdapter.updateExtRefSource(extRefInfo)); + + //Then + assertThat(extRef.getSrcCBName()).isEqualTo(extRefInfo.getSourceInfo().getSrcCBName()); + assertThat(extRef.getSrcLDInst()).isEqualTo(extRefInfo.getSourceInfo().getSrcLDInst()); + assertThat(extRef.getLnClass().contains(extRefInfo.getSourceInfo().getSrcLNClass())); + + } + + private ExtRefInfo givenCompleteExtRefInfo() { ExtRefInfo extRefInfo = new ExtRefInfo(); - assertThrows(IllegalArgumentException.class, () ->lnAdapter.updateExtRefSource(extRefInfo)); extRefInfo.setSignalInfo(new ExtRefSignalInfo()); - assertThrows(IllegalArgumentException.class, () ->lnAdapter.updateExtRefSource(extRefInfo)); extRefInfo.setBindingInfo(new ExtRefBindingInfo()); - assertThrows(IllegalArgumentException.class, () ->lnAdapter.updateExtRefSource(extRefInfo)); - extRefInfo.getSignalInfo().setPDA("da11.bda111.bda112.bda113"); extRefInfo.getSignalInfo().setPDO("Do11.sdo11"); extRefInfo.getSignalInfo().setIntAddr("INT_ADDR11"); @@ -208,40 +263,35 @@ void testUpdateExtRefSource() throws Exception { extRefInfo.getSourceInfo().setSrcLNInst(extRefInfo.getBindingInfo().getLnInst()); extRefInfo.getSourceInfo().setSrcLNClass(extRefInfo.getBindingInfo().getLnClass()); extRefInfo.getSourceInfo().setSrcPrefix(extRefInfo.getBindingInfo().getPrefix()); - - TExtRef extRef = assertDoesNotThrow( () ->lnAdapter.updateExtRefSource(extRefInfo)); - assertEquals(extRefInfo.getSourceInfo().getSrcCBName(), extRef.getSrcCBName()); - assertEquals(extRefInfo.getSourceInfo().getSrcLDInst(), extRef.getSrcLDInst()); - assertTrue(extRef.getLnClass().contains(extRefInfo.getSourceInfo().getSrcLNClass()) ); - + return extRefInfo; } @Test - void testAddDOI(){ + void testAddDOI() { TLN tln = new TLN(); tln.getLnClass().add(DTO.HOLDER_LN_CLASS); tln.setPrefix(DTO.HOLDER_LN_PREFIX); tln.setInst(DTO.HOLDER_LN_INST); - LNAdapter lnAdapter = new LNAdapter(null,tln); + LNAdapter lnAdapter = new LNAdapter(null, tln); DOIAdapter doiAdapter = lnAdapter.addDOI("Do"); - assertEquals("Do",doiAdapter.getCurrentElem().getName()); + assertEquals("Do", doiAdapter.getCurrentElem().getName()); } @Test - void testGetLNodeName(){ + void testGetLNodeName() { TLN tln = new TLN(); tln.getLnClass().add(DTO.HOLDER_LN_CLASS); tln.setPrefix(DTO.HOLDER_LN_PREFIX); tln.setInst(DTO.HOLDER_LN_INST); - AbstractLNAdapter lnAdapter = new LNAdapter(null,tln); + AbstractLNAdapter lnAdapter = new LNAdapter(null, tln); String exp = DTO.HOLDER_LN_PREFIX + DTO.HOLDER_LN_CLASS + DTO.HOLDER_LN_INST; - assertEquals(exp,lnAdapter.getLNodeName()); + assertEquals(exp, lnAdapter.getLNodeName()); LN0 ln0 = new LN0(); ln0.getLnClass().add(TLLN0Enum.LLN_0.value()); - lnAdapter = new LN0Adapter(null,ln0); - assertEquals(TLLN0Enum.LLN_0.value(),lnAdapter.getLNodeName()); + lnAdapter = new LN0Adapter(null, ln0); + assertEquals(TLLN0Enum.LLN_0.value(), lnAdapter.getLNodeName()); } @Test @@ -286,13 +336,13 @@ void testGetDAI() throws Exception { SCL scd = SclTestMarshaller.getSCLFromFile("/ied-test-schema-conf/scd_with_dai_test.xml"); SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iAdapter = assertDoesNotThrow(() -> sclRootAdapter.getIEDAdapterByName("IED_NAME")); - LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(()-> iAdapter.getLDeviceAdapterByLdInst("LDSUIED").get()); - LNAdapter lnAdapter = lDeviceAdapter.getLNAdapter("PIOC","1", null); - var rDtts = lnAdapter.getDAI(new ResumedDataTemplate(),true); + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(() -> iAdapter.getLDeviceAdapterByLdInst("LDSUIED").get()); + LNAdapter lnAdapter = lDeviceAdapter.getLNAdapter("PIOC", "1", null); + var rDtts = lnAdapter.getDAI(new ResumedDataTemplate(), true); assertFalse(rDtts.isEmpty()); } - private LNAdapter initLNAdapter(TLN tln){ + private LNAdapter initLNAdapter(TLN tln) { LDeviceAdapter lDeviceAdapter = Mockito.mock(LDeviceAdapter.class); TLDevice tlDevice = Mockito.mock(TLDevice.class); Mockito.when(lDeviceAdapter.getCurrentElem()).thenReturn(tlDevice); @@ -301,7 +351,7 @@ private LNAdapter initLNAdapter(TLN tln){ tln.setLnType(DTO.LN_TYPE); tln.setPrefix(DTO.HOLDER_LN_PREFIX); Mockito.when(tlDevice.getLN()).thenReturn(List.of(tln)); - return assertDoesNotThrow( () -> new LNAdapter(lDeviceAdapter,tln)); + return assertDoesNotThrow(() -> new LNAdapter(lDeviceAdapter, tln)); } @Test @@ -309,8 +359,8 @@ void addPrivate() throws Exception { SCL scd = SclTestMarshaller.getSCLFromFile("/ied-test-schema-conf/scd_with_dai_test.xml"); SclRootAdapter sclRootAdapter = new SclRootAdapter(scd); IEDAdapter iAdapter = assertDoesNotThrow(() -> sclRootAdapter.getIEDAdapterByName("IED_NAME")); - LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(()-> iAdapter.getLDeviceAdapterByLdInst("LDSUIED").get()); - LNAdapter lnAdapter = lDeviceAdapter.getLNAdapter("PIOC","1", null); + LDeviceAdapter lDeviceAdapter = assertDoesNotThrow(() -> iAdapter.getLDeviceAdapterByLdInst("LDSUIED").get()); + LNAdapter lnAdapter = lDeviceAdapter.getLNAdapter("PIOC", "1", null); TPrivate tPrivate = new TPrivate(); tPrivate.setType("Private Type"); tPrivate.setSource("Private Source"); @@ -330,4 +380,4 @@ void elementXPath() { assertThat(result).isEqualTo("LN[@lnClass=\"LN_CLASS_H\" and @inst=\"1\" and @lnType=\"LN_TYPE\"]"); } -} \ No newline at end of file +} diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/marshaller/MarshallerWrapper.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/marshaller/MarshallerWrapper.java index 0ddce33f3..631309c34 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/marshaller/MarshallerWrapper.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/testhelpers/marshaller/MarshallerWrapper.java @@ -14,7 +14,9 @@ import javax.xml.transform.Result; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; -import java.io.*; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.StringWriter; @Slf4j public class MarshallerWrapper { diff --git a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/UtilsTest.java b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/UtilsTest.java index 24ea812f3..aefe3279f 100644 --- a/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/UtilsTest.java +++ b/sct-commons/src/test/java/org/lfenergy/compas/sct/commons/util/UtilsTest.java @@ -4,8 +4,10 @@ package org.lfenergy.compas.sct.commons.util; +import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.junit.platform.commons.support.ReflectionSupport; @@ -187,4 +189,51 @@ public static Stream> xpathAttributeFilterEmptyCollectionSour Arrays.asList(new String[5]) ); } + + @ParameterizedTest + @MethodSource("equalsOrBothBlankMatchingSource") + void equalsOrBothBlank_should_be_true(String s1, String s2) { + // Given : parameters + // When + boolean result = Utils.equalsOrBothBlank(s1, s2); + // Then + Assertions.assertThat(result).isTrue(); + } + + @ParameterizedTest + @MethodSource("equalsOrBothBlankNotMatchingSource") + void equalsOrBothBlank_should_be_false(String s1, String s2) { + // Given : parameters + // When + boolean result = Utils.equalsOrBothBlank(s1, s2); + // Then + Assertions.assertThat(result).isFalse(); + } + + public static Stream equalsOrBothBlankMatchingSource() { + return Stream.of( + Arguments.of("a", "a"), + Arguments.of("", ""), + Arguments.of(" ", " "), + Arguments.of(null, null), + Arguments.of("", null), + Arguments.of(null, ""), + Arguments.of(" ", null), + Arguments.of(null, " "), + Arguments.of("", " "), + Arguments.of(" ", "") + ); + } + + public static Stream equalsOrBothBlankNotMatchingSource() { + return Stream.of( + Arguments.of("a", "b"), + Arguments.of("a", ""), + Arguments.of("a", " "), + Arguments.of("a", null), + Arguments.of("", "a"), + Arguments.of(" ", "a"), + Arguments.of( null, "a") + ); + } } diff --git a/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_success.xml b/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_success.xml new file mode 100644 index 000000000..66c8cc057 --- /dev/null +++ b/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_success.xml @@ -0,0 +1,73 @@ + + + + + + +
        + + + + + + + + + + + + on + + + + + + + + + + + + + + + + + + + + + + + + + + on + + + + + + + + + + + + + + + + + + + + + + + on + off + test + + + 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 new file mode 100644 index 000000000..17b090745 --- /dev/null +++ b/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_with_extref_errors.xml @@ -0,0 +1,158 @@ + + + + + + +
        + + + + + + + + + + + + + on + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + off + + + + + + + + + + + + + + + + test + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + + + + + + + + + + + off + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + off + test + + + diff --git a/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_with_ied_errors.xml b/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_with_ied_errors.xml new file mode 100644 index 000000000..b8571944a --- /dev/null +++ b/sct-commons/src/test/resources/scd-extref-iedname/scd_set_extref_iedname_with_ied_errors.xml @@ -0,0 +1,87 @@ + + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + off + test + + + diff --git a/sct-commons/src/test/resources/scd-ldevice-adapter/scd_ldevice.xml b/sct-commons/src/test/resources/scd-ldevice-adapter/scd_ldevice.xml new file mode 100644 index 000000000..3d399f2e6 --- /dev/null +++ b/sct-commons/src/test/resources/scd-ldevice-adapter/scd_ldevice.xml @@ -0,0 +1,50 @@ + + + + + + +
        + + + + + + + + + on + + + + + + + + + + + + + + + + + + + + + + + + + + + + + on + off + test + + + 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/issue_165_enhance_68_Test_Dai_Updatable.scd similarity index 100% rename from sct-commons/src/test/resources/scd-refresh-lnode/issue68_Test_Dai_Not_Updatable.scd rename to sct-commons/src/test/resources/scd-refresh-lnode/issue_165_enhance_68_Test_Dai_Updatable.scd diff --git a/sct-commons/src/test/resources/scl-srv-scd-extref-cb/issue_175_scd_get_cbs_test.xml b/sct-commons/src/test/resources/scl-srv-scd-extref-cb/issue_175_scd_get_cbs_test.xml new file mode 100644 index 000000000..61fd08fb5 --- /dev/null +++ b/sct-commons/src/test/resources/scl-srv-scd-extref-cb/issue_175_scd_get_cbs_test.xml @@ -0,0 +1,164 @@ + + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Completed-diff + + + \ No newline at end of file diff --git a/sct-data/pom.xml b/sct-data/pom.xml index 248813512..88da7f986 100644 --- a/sct-data/pom.xml +++ b/sct-data/pom.xml @@ -39,4 +39,12 @@ test - \ No newline at end of file + + + + org.apache.maven.plugins + maven-source-plugin + + + +