Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
massifben committed Dec 16, 2024
1 parent b487321 commit b80e273
Show file tree
Hide file tree
Showing 5 changed files with 328 additions and 68 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// SPDX-FileCopyrightText: 2024 RTE FRANCE
//
// SPDX-License-Identifier: Apache-2.0

package org.lfenergy.compas.sct.commons;

import org.apache.commons.lang3.StringUtils;
import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.scl2007b4.model.TAnyLN;
import org.lfenergy.compas.scl2007b4.model.TBaseElement;
import org.lfenergy.compas.scl2007b4.model.TPredefinedBasicTypeEnum;
import org.lfenergy.compas.sct.commons.domain.DataAttribute;
import org.lfenergy.compas.sct.commons.domain.DoLinkedToDa;
import org.lfenergy.compas.sct.commons.domain.DoLinkedToDaFilter;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
import org.lfenergy.compas.sct.commons.util.CommonConstants;

import java.util.List;
import java.util.Optional;

public class LNodeStatusService {

private final LnService lnService = new LnService();
private final DataTypeTemplatesService dataTypeTemplatesService = new DataTypeTemplatesService();

public List<SclReportItem> updateLnModStValBasedOnLNodeStatus(SCL scl) {
scl.getSubstation().stream()
.flatMap(tSubstation -> tSubstation.getVoltageLevel().stream())
.flatMap(tVoltageLevel -> tVoltageLevel.getBay().stream())
.flatMap(tBay -> tBay.getFunction().stream())
.flatMap(tFunction -> tFunction.getLNode().stream())
.map(tlNode -> {
String lNodeLnodeStatus = extractStringPrivate(tlNode, "COMPAS-LNodeStatus")
.orElseThrow(); // FIXME
TAnyLN tAnyLN = findLn(scl, tlNode.getIedName(), tlNode.getLdInst(), tlNode.getLnClass().getFirst(), tlNode.getLnInst(), tlNode.getPrefix())
.orElseThrow();// FIXME
String lnLNodeStatus = extractStringPrivate(tAnyLN, "COMPAS-LNodeStatus")
.orElseThrow();
switch (lNodeLnodeStatus) {
case "on" -> {
if (lnLNodeStatus.contains("on")) {
// Met à jour Mod stVal s'il existe
lnService.getDaiModStVal(tAnyLN)
.ifPresent(tdai -> {

dataTypeTemplatesService.findDoLinkedToDa(scl.getDataTypeTemplates(), tAnyLN.getLnType(), DoLinkedToDaFilter.from(CommonConstants.MOD_DO_NAME, CommonConstants.STVAL_DA_NAME))
.map(DoLinkedToDa::dataAttribute)
.filter(dataAttribute -> TPredefinedBasicTypeEnum.ENUM.equals(dataAttribute.getBType()))
.map(DataAttribute::getType);
});
} else {
// erreur // FIXME
}
}
case "of" -> {
if (lnLNodeStatus.contains("off")) {
// Met à jour Mod stVal s'il existe
} else {
// erreur // FIXME
}
}
default -> {
// erreur // FIXME
}
}
return null;
}
);

return List.of();
}

private static Optional<String> extractStringPrivate(TBaseElement tBaseElement, String privateType) {
return tBaseElement.getPrivate().stream()
.filter(tPrivate -> privateType.equals(tPrivate.getType()))
.flatMap(tPrivate -> tPrivate.getContent().stream())
.filter(String.class::isInstance)
.map(String.class::cast)
.filter(StringUtils::isNotBlank)
.findFirst();
}

private Optional<TAnyLN> findLn(SCL scl, String iedName, String ldInst, String lnClass, String lnInst, String prefix) {
return scl.getIED().stream()
.filter(tied -> iedName.equals(tied.getName()))
.findFirst()
.flatMap(tied -> new LdeviceService().findLdevice(tied, tlDevice -> ldInst.equals(tlDevice.getInst())))
.flatMap(tlDevice -> lnService.findAnyLn(tlDevice, tAnyLN -> lnService.matchesLn(tAnyLN, lnInst, lnClass, prefix)));

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.lfenergy.compas.sct.commons.util.ActiveStatus;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
Expand Down Expand Up @@ -60,33 +59,37 @@ public Optional<TLN> findLn(TLDevice tlDevice, Predicate<TLN> lnPredicate) {
* @return the Lnode Status
*/
public ActiveStatus getLnStatus(TAnyLN tAnyLN, LN0 ln0) {
Optional<ActiveStatus> ln0Status = getDaiModStval(ln0);
return getDaiModStval(tAnyLN).filter(ActiveStatus.OFF::equals).orElseGet(() -> ln0Status.orElse(ActiveStatus.OFF));
Optional<ActiveStatus> ln0Status = getDaiModStValValue(ln0);
return getDaiModStValValue(tAnyLN).filter(ActiveStatus.OFF::equals).orElseGet(() -> ln0Status.orElse(ActiveStatus.OFF));
}

public Optional<ActiveStatus> getDaiModStval(TAnyLN tAnyLN) {
public Optional<ActiveStatus> getDaiModStValValue(TAnyLN tAnyLN) {
return getDaiModStVal(tAnyLN)
.stream()
.flatMap(tdai -> tdai.getVal().stream())
.map(TVal::getValue)
.findFirst()
.map(ActiveStatus::fromValue);
}

public Optional<TDAI> getDaiModStVal(TAnyLN tAnyLN) {
return tAnyLN
.getDOI()
.stream()
.filter(tdoi -> MOD_DO_NAME.equals(tdoi.getName()))
.findFirst()
.flatMap(tdoi -> tdoi.getSDIOrDAI()
.stream()
.filter(dai -> dai.getClass().equals(TDAI.class))
.map(TDAI.class::cast)
.filter(tdai -> STVAL_DA_NAME.equals(tdai.getName()))
.map(TDAI::getVal)
.flatMap(Collection::stream)
.findFirst()
.map(TVal::getValue))
.map(ActiveStatus::fromValue);
.flatMap(tdoi -> tdoi.getSDIOrDAI().stream())
.filter(TDAI.class::isInstance)
.map(TDAI.class::cast)
.filter(tdai -> STVAL_DA_NAME.equals(tdai.getName()))
.findFirst();
}

public Stream<TAnyLN> getActiveLns(TLDevice tlDevice) {
LN0 ln0 = tlDevice.getLN0();
Stream<TLN> tlnStream = tlDevice.getLN()
.stream()
.filter(tln -> ActiveStatus.ON.equals(getLnStatus(tln, ln0)));
Stream<LN0> ln0Stream = Stream.of(ln0).filter(ln02 -> getDaiModStval(ln02).map(ActiveStatus.ON::equals).orElse(false));
Stream<LN0> ln0Stream = Stream.of(ln0).filter(ln02 -> getDaiModStValValue(ln02).map(ActiveStatus.ON::equals).orElse(false));
return Stream.concat(ln0Stream, tlnStream);
}

Expand All @@ -99,7 +102,7 @@ public Optional<TDAI> getDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDaFilter doLi
return tAnyLN.getDOI().stream().filter(doi -> doi.getName().equals(doLinkedToDaFilter.doName()))
.findFirst()
.flatMap(doi -> {
if(structNamesList.size() > 1) {
if (structNamesList.size() > 1) {
String firstSDIName = structNamesList.removeFirst();
return this.getSdiByName(doi, firstSDIName)
.map(intermediateSdi -> findSDIByStructName(intermediateSdi, structNamesList))
Expand All @@ -116,7 +119,7 @@ public Optional<TDAI> getDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDaFilter doLi
return Optional.empty();
})
.stream().findFirst();
} else if(structNamesList.size() == 1){
} else if (structNamesList.size() == 1) {
return doi.getSDIOrDAI().stream()
.filter(unNaming -> unNaming.getClass().equals(TDAI.class))
.map(TDAI.class::cast)
Expand All @@ -129,16 +132,16 @@ public Optional<TDAI> getDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDaFilter doLi

@Override
public void updateOrCreateDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDa doLinkedToDa) {
createDoiSdiDaiChainIfNotExists(tAnyLN, doLinkedToDa.getDataObject(), doLinkedToDa.getDataAttribute())
createDoiSdiDaiChainIfNotExists(tAnyLN, doLinkedToDa.dataObject(), doLinkedToDa.dataAttribute())
.ifPresent(tdai -> {
List<DaVal> daiVals = doLinkedToDa.getDataAttribute().getDaiValues();
if(!hasSettingGroup(tdai) && daiVals.size() == 1 && daiVals.getFirst().settingGroup() == null) {
List<DaVal> daiVals = doLinkedToDa.dataAttribute().getDaiValues();
if (!hasSettingGroup(tdai) && daiVals.size() == 1 && daiVals.getFirst().settingGroup() == null) {
String value = daiVals.getFirst().val();
tdai.getVal().stream().findFirst()
.ifPresentOrElse(tVal -> tVal.setValue(value),
() -> tdai.getVal().add(newVal(value)));
} else {
for (DaVal daVal: daiVals) {
for (DaVal daVal : daiVals) {
tdai.getVal().stream()
.filter(tValElem -> tValElem.isSetSGroup() && tValElem.getSGroup() == daVal.settingGroup())
.findFirst()
Expand All @@ -152,11 +155,11 @@ public void updateOrCreateDOAndDAInstances(TAnyLN tAnyLN, DoLinkedToDa doLinkedT
public void completeFromDAInstance(TIED tied, String ldInst, TAnyLN anyLN, DoLinkedToDa doLinkedToDa) {
getDOAndDAInstances(anyLN, doLinkedToDa.toFilter())
.ifPresent(tdai -> {
if(tdai.isSetVal()) {
doLinkedToDa.getDataAttribute().addDaVal(tdai.getVal());
if (tdai.isSetVal()) {
doLinkedToDa.dataAttribute().addDaVal(tdai.getVal());
}
if(doLinkedToDa.getDataAttribute().getFc() == TFCEnum.SG || doLinkedToDa.getDataAttribute().getFc() == TFCEnum.SE) {
if(hasSettingGroup(tdai)) {
if (doLinkedToDa.dataAttribute().getFc() == TFCEnum.SG || doLinkedToDa.dataAttribute().getFc() == TFCEnum.SE) {
if (hasSettingGroup(tdai)) {
boolean isIedHasConfSG = tied.isSetAccessPoint() &&
tied.getAccessPoint().stream()
.filter(tAccessPoint -> tAccessPoint.getServer() != null
Expand All @@ -166,13 +169,13 @@ public void completeFromDAInstance(TIED tied, String ldInst, TAnyLN anyLN, DoLin
&& tAccessPoint.getServices() != null
&& tAccessPoint.getServices().getSettingGroups() != null
&& tAccessPoint.getServices().getSettingGroups().getConfSG() != null);
doLinkedToDa.getDataAttribute().setValImport((!tdai.isSetValImport() || tdai.isValImport()) && isIedHasConfSG);
doLinkedToDa.dataAttribute().setValImport((!tdai.isSetValImport() || tdai.isValImport()) && isIedHasConfSG);
} else {
log.warn(String.format("Inconsistency in the SCD file - DAI= %s with fc= %s must have a sGroup attribute", tdai.getName(), doLinkedToDa.getDataAttribute().getFc()));
doLinkedToDa.getDataAttribute().setValImport(false);
}
} else if(tdai.isSetValImport()) {
doLinkedToDa.getDataAttribute().setValImport(tdai.isValImport());
log.warn(String.format("Inconsistency in the SCD file - DAI= %s with fc= %s must have a sGroup attribute", tdai.getName(), doLinkedToDa.dataAttribute().getFc()));
doLinkedToDa.dataAttribute().setValImport(false);
}
} else if (tdai.isSetValImport()) {
doLinkedToDa.dataAttribute().setValImport(tdai.isValImport());
}
});
}
Expand All @@ -198,22 +201,22 @@ private Optional<TDAI> createDoiSdiDaiChainIfNotExists(TAnyLN tAnyLN, DataObject

TDOI doi = tAnyLN.getDOI().stream().filter(doi1 -> doi1.getName().equals(dataObject.getDoName()))
.findFirst()
.orElseGet(()-> {
.orElseGet(() -> {
TDOI newDOI = new TDOI();
newDOI.setName(dataObject.getDoName());
tAnyLN.getDOI().add(newDOI);
return newDOI;
});
if(structInstances.size() > 1){
if (structInstances.size() > 1) {
TSDI firstSDI = findOrCreateSDIFromDOI(doi, structInstances.getFirst());
TSDI lastSDI = findOrCreateSDIByStructName(firstSDI, structInstances);
if(structInstances.size() == 1){
if (structInstances.size() == 1) {
return lastSDI.getSDIOrDAI().stream()
.filter(tUnNaming -> tUnNaming.getClass().equals(TDAI.class))
.map(TDAI.class::cast)
.filter(tdai -> tdai.getName().equals(structInstances.getFirst()))
.map(tdai -> {
if(tdai.isSetValImport()) {
if (tdai.isSetValImport()) {
tdai.setValImport(dataAttribute.isValImport());
}
return tdai;
Expand All @@ -226,13 +229,13 @@ private Optional<TDAI> createDoiSdiDaiChainIfNotExists(TAnyLN tAnyLN, DataObject
return Optional.of(newDAI);
});
}
} else if(structInstances.size() == 1){
} else if (structInstances.size() == 1) {
return doi.getSDIOrDAI().stream()
.filter(tUnNaming -> tUnNaming.getClass().equals(TDAI.class))
.map(TDAI.class::cast)
.filter(tdai -> tdai.getName().equals(structInstances.getFirst()))
.map(tdai -> {
if(tdai.isSetValImport()) tdai.setValImport(dataAttribute.isValImport());
if (tdai.isSetValImport()) tdai.setValImport(dataAttribute.isValImport());
return tdai;
})
.findFirst()
Expand All @@ -247,7 +250,7 @@ private Optional<TDAI> createDoiSdiDaiChainIfNotExists(TAnyLN tAnyLN, DataObject
}

private TSDI findSDIByStructName(TSDI tsdi, List<String> sdiNames) {
if(sdiNames.isEmpty()) return tsdi;
if (sdiNames.isEmpty()) return tsdi;
return this.getSdiByName(tsdi, sdiNames.getFirst())
.map(sdi1 -> {
sdiNames.removeFirst();
Expand Down Expand Up @@ -294,14 +297,13 @@ private Optional<TSDI> getSdiByName(TSDI sdi, String sdiName) {
}

/**
*
* @param sdi TSDI
* @param sdi TSDI
* @param structName list start with sdi name
* @return already existing TSDI or newly created TSDI from given TSDI
*/
private TSDI findOrCreateSDIByStructName(TSDI sdi, List<String> structName) {
structName.removeFirst();
if(structName.isEmpty() || structName.size() == 1) return sdi;
if (structName.isEmpty() || structName.size() == 1) return sdi;
return findOrCreateSDIByStructName(findOrCreateSDIFromSDI(sdi, structName.getFirst()), structName);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: 2024 RTE FRANCE
//
// SPDX-License-Identifier: Apache-2.0

package org.lfenergy.compas.sct.commons;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
import static org.lfenergy.compas.sct.commons.testhelpers.SclHelper.*;

class LNodeStatusServiceTest {

private LNodeStatusService lNodeStatusService;

@BeforeEach
void setUp() throws Exception {
lNodeStatusService = new LNodeStatusService();
}

@Test
void updateLnStatusBasedOnPrivateLNodeStatus_should_succeed() {
// Given
SCL scl = SclTestMarshaller.getSCLFromFile("/scl-lnodestatus/lnodestatus.scd");
// When
List<SclReportItem> sclReportItems = lNodeStatusService.updateLnModStValBasedOnLNodeStatus(scl);
// Then
assertThat(sclReportItems).isEmpty();
assertThat(getValue(findDai(findLn(scl, "IED_NAME_1", "LDEVICE_1", "PDIS", "1", ""), "Mod.stVal")))
.isEqualTo("on");
}


}
Loading

0 comments on commit b80e273

Please sign in to comment.