Skip to content

Commit

Permalink
[68][164] Activation used LDevice and Deactivation unused LDevice
Browse files Browse the repository at this point in the history
Signed-off-by: Aliou DIAITE <aliou.diaite@rte-france.com>
Signed-off-by: Samir Romdhani <samir.romdhani@rte-france.com>
  • Loading branch information
samirromdhani committed Sep 23, 2022
1 parent b527d99 commit 2ebc36e
Show file tree
Hide file tree
Showing 41 changed files with 2,434 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -322,4 +322,11 @@ public void setValImport(boolean valImport) {
public boolean isValImport(){
return daName.isValImport();
}

public ResumedDataTemplate setNewVal(String daiValue) {
TVal newDaiVal = new TVal();
newDaiVal.setValue(daiValue);
this.setDaiValues(List.of(newDaiVal));
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* // SPDX-FileCopyrightText: 2022 RTE FRANCE
* //
* // SPDX-License-Identifier: Apache-2.0
*/

package org.lfenergy.compas.sct.commons.dto;

import lombok.*;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;

import java.util.ArrayList;
import java.util.List;

@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@Builder
public class SclReport {

private SclRootAdapter scdFile;

private List<ErrorDescription> errorDescriptionList = new ArrayList<>();

public boolean isSuccess() {
return errorDescriptionList.isEmpty();
}

@Getter
@Setter
@AllArgsConstructor
@ToString
@EqualsAndHashCode
@Builder
public static class ErrorDescription{
private String xpath;
private String message;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// SPDX-FileCopyrightText: 2022 RTE FRANCE
//
// SPDX-License-Identifier: Apache-2.0


package org.lfenergy.compas.sct.commons.scl;

import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.tuple.Pair;
import org.lfenergy.compas.scl2007b4.model.TCompasLDeviceStatus;
import org.lfenergy.compas.sct.commons.dto.ResumedDataTemplate;
import org.lfenergy.compas.sct.commons.util.STValEnum;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Getter
@Setter
public class LDeviceActivation {

private final List<Pair<String, String>> iedNameLdInstList;

private TCompasLDeviceStatus compasLDeviceStatus;
private boolean isUpdatable;
private ResumedDataTemplate resumedDataTemplate;
private List<String> errorMessages = new ArrayList<>();

public LDeviceActivation(List<Pair<String, String>> iedNameLdInstList) {
this.iedNameLdInstList = iedNameLdInstList;
}

public void checkLDeviceActivationStatus(String iedName, String ldInst, TCompasLDeviceStatus compasLDeviceStatus, Set<String> enumValues) {
if (!enumValues.contains(STValEnum.ON.value) && !enumValues.contains(STValEnum.OFF.value)) {
errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s cannot be activated or desactivated because its BehaviourKind Enum contains NOT 'on' AND NOT 'off'.",
iedName, ldInst));
}
if (!enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) {
if (isAuthorized(iedName, ldInst)) {
errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s cannot be set to 'on' but has been selected into SSD: this case should not occur.", iedName, ldInst));
} else {
isUpdatable = true;
resumedDataTemplate.setNewVal(STValEnum.OFF.value);
}
}
if(compasLDeviceStatus.equals(TCompasLDeviceStatus.ACTIVE) ||
compasLDeviceStatus.equals(TCompasLDeviceStatus.UNTESTED)){
isAuthorizedToActivateLDevice(iedName, ldInst, enumValues);
}
if(compasLDeviceStatus.equals(TCompasLDeviceStatus.INACTIVE)){
isAuthorizedToDeactivateLDevice(iedName, ldInst, enumValues);
}
}

private void isAuthorizedToActivateLDevice(String iedName, String ldInst, Set<String> enumValues) {
if (!enumValues.contains(STValEnum.OFF.value) && enumValues.contains(STValEnum.ON.value)) {
if (isAuthorized(iedName, ldInst)) {
isUpdatable = true;
resumedDataTemplate.setNewVal(STValEnum.ON.value);
} else {
errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s cannot be set to 'off' but has not been selected into SSD: this case should not occur.", iedName, ldInst));
}
}
if (enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) {
isUpdatable = true;
if (isAuthorized(iedName, ldInst)) {
resumedDataTemplate.setNewVal(STValEnum.ON.value);
} else {
resumedDataTemplate.setNewVal(STValEnum.OFF.value);
}
}

}

private void isAuthorizedToDeactivateLDevice(String iedName, String ldInst, Set<String> enumValues) {
if (!enumValues.contains(STValEnum.OFF.value) && enumValues.contains(STValEnum.ON.value)) {
if (isAuthorized(iedName, ldInst)) {
errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s is not qualified into STD but has been selected into SSD: this case should not occur.",
iedName, ldInst));
} else {
errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s cannot be set to 'off' but has not been selected into SSD: this case should not occur.",
iedName, ldInst));
}
}
if (enumValues.contains(STValEnum.ON.value) && enumValues.contains(STValEnum.OFF.value)) {
if (isAuthorized(iedName, ldInst)) {
errorMessages.add(String.format("Unexpected error: The IED@%s/LDevice@%s is not qualified into STD but has been selected into SSD: this case should not occur.",
iedName, ldInst));
} else {
isUpdatable = true;
resumedDataTemplate.setNewVal(STValEnum.OFF.value);
}
}
}

private boolean isAuthorized(String iedName, String ldInst){
return iedNameLdInstList.contains(Pair.of(iedName, ldInst));
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ protected boolean amRootElement(){
return parentAdapter == null;
}

/**
* Returns XPath path to current element
* @return message as <em>undefined</em>
*/
protected abstract String elementXPath();

protected void customInit() {
// do nothing
}
Expand Down Expand Up @@ -109,12 +115,4 @@ public String getXPath(){
return parentXpath + "/" + elementXPath();
}

/**
* Returns XPath path to current element
* @return message as <em>undefined</em>
*/
protected String elementXPath(){
return String.format("undefined(%s)", currentElem.getClass().getSimpleName());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
Expand Down Expand Up @@ -140,6 +141,19 @@ public SubstationAdapter getSubstationAdapter(String ssName) throws ScdException
return new SubstationAdapter(this,ssName);
}

/**
* TODO
* @return
* @throws ScdException
*/
public SubstationAdapter getSubstationAdapter() throws ScdException {
TSubstation tSubstation = currentElem.getSubstation()
.stream()
.findFirst()
.orElseThrow(() -> new ScdException("No Substation in SCL file"));
return new SubstationAdapter(this, tSubstation);
}

/**
* Add Header to SCL root node
* @param hId SCL Header ID
Expand Down Expand Up @@ -275,4 +289,5 @@ public IEDAdapter checkObjRef(String val) throws ScdException {
}
throw new ScdException("Invalid ObjRef: " + val);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -680,4 +680,27 @@ public static void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final S
.forEach(LNAdapter::removeAllControlBlocksAndDatasets);
}

/**
* Activate used LDevice and Deactivate unused LDevice in {@link TLNode <em><b>TLNode </b></em>}
* @param scd SCL file for which LDevice should be activated or deactivated
* @return SclReport Object that contain SCL file and set of errors
*/
public static SclReport updateLDeviceStatus(SCL scd) {
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
final List<Pair<String, String>> iedNameLdInstList = SubstationService.getLDevicesFromLNode(sclRootAdapter, true);
LDeviceActivation lDeviceActivate = new LDeviceActivation(iedNameLdInstList);
Optional<List<SclReport.ErrorDescription>> errors = sclRootAdapter.getIEDAdapters().stream()
.map(IEDAdapter::getLDeviceAdapters)
.flatMap(Collection::stream)
.map(LDeviceAdapter::getLN0Adapter)
.map(ln0Adapter -> ln0Adapter.checkAndUpdateLDevice(lDeviceActivate))
.reduce((partialSclReportErrors, sclReportErrors) -> {
partialSclReportErrors.addAll(sclReportErrors);
return partialSclReportErrors;
});
SclReport sclReport = new SclReport();
errors.ifPresent(errorDescriptions -> sclReport.getErrorDescriptionList().addAll(errorDescriptions));
sclReport.setScdFile(sclRootAdapter);
return sclReport;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,17 @@

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.scl2007b4.model.TBay;
import org.lfenergy.compas.scl2007b4.model.TSubstation;
import org.lfenergy.compas.scl2007b4.model.TVoltageLevel;
import org.apache.commons.lang3.tuple.Pair;
import org.lfenergy.compas.scl2007b4.model.*;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.scl.sstation.BayAdapter;
import org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter;
import org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
* A representation of the <em><b>{@link SubstationService SubstationService}</b></em>.
* <p>
* The following features are supported:
* </p>
* <ul>
* <li>{@link SubstationService#addSubstation(SCL, SCL) <em>Adds the <b>Substation </b> object from given <b>SCL </b> object</em>}</li>
* <li>{@link SubstationService#updateVoltageLevel(SubstationAdapter, TVoltageLevel) <em>Adds the <b>TVoltageLevel </b> element under <b>TSubstation </b> reference object</em>}</li>
* <li>{@link SubstationService#updateBay(VoltageLevelAdapter, TBay) <em>Adds the <b>TBay </b> element under <b>TVoltageLevel </b> reference object</em>}</li>
* </ul>
* @see org.lfenergy.compas.sct.commons.scl.sstation.SubstationAdapter
* @see org.lfenergy.compas.sct.commons.scl.sstation.VoltageLevelAdapter
* @see org.lfenergy.compas.sct.commons.scl.sstation.BayAdapter
* @see org.lfenergy.compas.sct.commons.scl.sstation.FunctionAdapter
* @see org.lfenergy.compas.sct.commons.scl.sstation.LNodeAdapter
* @see org.lfenergy.compas.sct.commons.scl.PrivateService
*/
@Slf4j
public final class SubstationService {

Expand Down Expand Up @@ -112,4 +97,22 @@ private static void updateBay(@NonNull VoltageLevelAdapter scdVoltageLevelAdapte
}
}

/**
*
* @param sclRootAdapter
* @return
*/
public static List<Pair<String, String>> getLDevicesFromLNode(SclRootAdapter sclRootAdapter, boolean isLN0) {
if (!sclRootAdapter.getCurrentElem().isSetSubstation()) {
return new ArrayList<>();
}
return sclRootAdapter.getSubstationAdapter()
.streamVoltageLevelAdapters()
.flatMap(VoltageLevelAdapter::streamBayAdapters)
.flatMap(BayAdapter::streamFunctionAdapters)
.flatMap(functionAdapter -> functionAdapter.getCurrentElem().getLNode().stream())
.filter(tlNode -> !isLN0 || tlNode.getLnClass().contains(TLLN0Enum.LLN_0.value()))
.map(tlNode -> Pair.of(tlNode.getIedName(), tlNode.getLdInst()))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.lfenergy.compas.sct.commons.scl.SclElementAdapter;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.IEDAdapter;
import org.lfenergy.compas.sct.commons.util.Utils;

import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -58,6 +59,11 @@ public boolean amChildElementRef() {
return currentElem == parentAdapter.getCurrentElem().getCommunication();
}

@Override
protected String elementXPath() {
return "Communication";
}

/**
* Add Subnetwork node in Communication one.
* For that :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.scl2007b4.model.TConnectedAP;
import org.lfenergy.compas.scl2007b4.model.TPrivate;
import org.lfenergy.compas.sct.commons.scl.SclElementAdapter;
import org.lfenergy.compas.sct.commons.util.Utils;

import java.util.Optional;

Expand Down Expand Up @@ -45,6 +45,13 @@ protected boolean amChildElementRef() {
return parentAdapter.getCurrentElem().getConnectedAP().contains(currentElem);
}

@Override
protected String elementXPath() {
return String.format("ConnectedAP[apName=%s and iedName=%s]",
Utils.xpathAttributeFilter("apName", currentElem.isSetApName() ? currentElem.getApName() : null),
Utils.xpathAttributeFilter("iedName", currentElem.isSetIedName() ? currentElem.getApName() : null));
}

/**
* Returns the value of the <em><b>iedName</b></em> attribute.
* @return the value of the <em><b>iedName</b></em> attribute.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.lfenergy.compas.scl2007b4.model.TSubNetwork;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.scl.SclElementAdapter;
import org.lfenergy.compas.sct.commons.util.Utils;

import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -48,6 +49,12 @@ protected boolean amChildElementRef() {
return parentAdapter.getCurrentElem().getSubNetwork().contains(currentElem);
}

@Override
protected String elementXPath() {
return String.format("SubNetwork[name=%s]",
Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null));
}

/**
* Create a Connected Access Point for this subnetwork.<br/>
* <p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.lfenergy.compas.scl2007b4.model.TDA;
import org.lfenergy.compas.sct.commons.dto.DaTypeName;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.util.Utils;

/**
* A representation of the model object <em><b>{@link org.lfenergy.compas.scl2007b4.model.TDA DA}</b></em>.
Expand Down Expand Up @@ -57,6 +58,13 @@ protected boolean amChildElementRef() {
return parentAdapter.getCurrentElem().getSDOOrDA().contains(currentElem);
}

@Override
protected String elementXPath() {
return String.format("DA[name=%s and type=%s]",
Utils.xpathAttributeFilter("name", currentElem.isSetName() ? currentElem.getName() : null),
Utils.xpathAttributeFilter("type", currentElem.isSetType() ? currentElem.getType() : null));
}

/**
* Updates DA Type Name
* @param daTypeName DA Type Name to update
Expand Down
Loading

0 comments on commit 2ebc36e

Please sign in to comment.