Skip to content

Commit

Permalink
feat(#257): manage (update and/or create) monitoring LNs LSVS and LGO…
Browse files Browse the repository at this point in the history
…S for Control Blocks GOOSE and SMV

Signed-off-by: Aliou DIAITE <[email protected]>
  • Loading branch information
AliouDIAITE committed Mar 30, 2023
1 parent fd98b51 commit 5f759ed
Show file tree
Hide file tree
Showing 15 changed files with 1,050 additions and 200 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public class SclService {

private static final String UNKNOWN_LDEVICE_S_IN_IED_S = "Unknown LDevice (%s) in IED (%s)";
private static final String INVALID_OR_MISSING_ATTRIBUTES_IN_EXT_REF_BINDING_INFO = "Invalid or missing attributes in ExtRef binding info";
private static final String IED_TEST_NAME = "IEDTEST";

private SclService() {
throw new IllegalStateException("SclService class");
Expand Down Expand Up @@ -609,4 +610,20 @@ public static SclReport updateDoInRef(SCL scd) {
.toList();
return new SclReport(sclRootAdapter, sclReportItems);
}

/**
* Update and/or create Monitoring LNs (LSVS and LGOS) for bound GOOSE and SMV Control Blocks
*
* @param scd SCL file for which LNs (LSVS and LGOS) should be updated and/or created in each LDevice LDSUIED with matching ExtRef information
* @return SclReport Object that contain SCL file and set of errors
*/
public static SclReport manageMonitoringLns(SCL scd) {
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
List<SclReportItem> sclReportItems = sclRootAdapter.streamIEDAdapters()
.filter(iedAdapter -> !iedAdapter.getName().contains(IED_TEST_NAME))
.map(IEDAdapter::manageMonitoringLns)
.flatMap(List::stream)
.toList();
return new SclReport(sclRootAdapter, sclReportItems);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.lfenergy.compas.sct.commons.scl.ied.InputsAdapter.filterDuplicatedExtRefs;

/**
* A representation of the model object
* <em><b>{@link org.lfenergy.compas.scl2007b4.model.TAccessPoint AccessPoint}</b></em>.
Expand All @@ -35,7 +37,6 @@
public class AccessPointAdapter extends SclElementAdapter<IEDAdapter, TAccessPoint> {

public static final long MAX_OCCURRENCE_NO_LIMIT_VALUE = -1L;
private static final String CLIENT_IED_NAME = "The Client IED ";

/**
* Constructor
Expand Down Expand Up @@ -219,7 +220,7 @@ public Optional<SclReportItem> checkLimitationForBoundIedFcdas(List<TExtRef> tEx
* @param sclReportItems
* @param tExtRefs
*/
record ExtRefAnalyzeRecord(List<SclReportItem> sclReportItems, List<TExtRef> tExtRefs) {
public record ExtRefAnalyzeRecord(List<SclReportItem> sclReportItems, List<TExtRef> tExtRefs) {
}

/**
Expand All @@ -229,21 +230,14 @@ record ExtRefAnalyzeRecord(List<SclReportItem> sclReportItems, List<TExtRef> tEx
*/
public ExtRefAnalyzeRecord getAllCoherentExtRefForAnalyze() {
List<SclReportItem> sclReportItems = new ArrayList<>();
List<TExtRef> tExtRefList = new ArrayList<>();
streamLDeviceAdapters().map(lDeviceAdapter -> {
List<TExtRef> extRefs = lDeviceAdapter.getLN0Adapter().getExtRefs().stream().filter(TExtRef::isSetSrcCBName).collect(Collectors.toCollection(ArrayList::new));
sclReportItems.addAll(checkExtRefWithoutServiceType(extRefs, lDeviceAdapter.getLN0Adapter().getXPath()));
extRefs.removeIf(tExtRef -> !tExtRef.isSetServiceType());
return extRefs;
}).flatMap(Collection::stream).forEach(tExtRef -> {
if (tExtRefList.isEmpty())
tExtRefList.add(tExtRef);
else {
if (tExtRefList.stream().noneMatch(t -> isExtRefFeedBySameControlBlock(tExtRef, t)))
tExtRefList.add(tExtRef);
}
});
return new ExtRefAnalyzeRecord(sclReportItems, tExtRefList);
List<TExtRef> tExtRefList = streamLDeviceAdapters().map(lDeviceAdapter -> {
List<TExtRef> extRefs = lDeviceAdapter.getLN0Adapter().getExtRefs().stream().filter(TExtRef::isSetSrcCBName).collect(Collectors.toCollection(ArrayList::new));
sclReportItems.addAll(checkExtRefWithoutServiceType(extRefs, lDeviceAdapter.getLN0Adapter().getXPath()));
extRefs.removeIf(tExtRef -> !tExtRef.isSetServiceType());
return extRefs;
}).flatMap(Collection::stream)
.toList();
return new ExtRefAnalyzeRecord(sclReportItems, filterDuplicatedExtRefs(tExtRefList));
}

/**
Expand All @@ -262,25 +256,6 @@ private List<SclReportItem> checkExtRefWithoutServiceType(List<TExtRef> tExtRefs
.toList();
}

/**
* Checks if two ExtRefs fed by same Control Block for SCL limits analyze
* Nota : this equality is only for checking limitation check
*
* @param t1 extref to compare
* @param t2 extref to compare
* @return true if the two ExtRef are fed by same Control Block, otherwise false
*/
private static boolean isExtRefFeedBySameControlBlock(TExtRef t1, TExtRef t2) {
String srcLNClass1 = (t1.isSetSrcLNClass()) ? t1.getSrcLNClass().get(0) : TLLN0Enum.LLN_0.value();
String srcLNClass2 = (t2.isSetSrcLNClass()) ? t2.getSrcLNClass().get(0) : TLLN0Enum.LLN_0.value();
return Utils.equalsOrBothBlank(t1.getIedName(), t2.getIedName())
&& Utils.equalsOrBothBlank(t1.getSrcLDInst(), t2.getSrcLDInst())
&& srcLNClass1.equals(srcLNClass2)
&& Utils.equalsOrBothBlank(t1.getSrcLNInst(), t2.getSrcLNInst())
&& Utils.equalsOrBothBlank(t1.getSrcPrefix(), t2.getSrcPrefix())
&& t1.getServiceType().equals(t2.getServiceType());
}

/**
* Checks Control Blocks (Report, Goose, SMV) number limitation for bound IED
*
Expand All @@ -300,7 +275,6 @@ public List<SclReportItem> checkLimitationForBoundIEDControls(List<TExtRef> tExt
* Checks Control Block number limitation for bound IED
*
* @param tExtRefs list of ExtRefs referenced same ied
* @param msg message to display hen error occured
* @param servicesConfigEnum type of Control Block for which check is done
* @return Optional of encountered error or empty
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@
import org.lfenergy.compas.sct.commons.scl.PrivateService;
import org.lfenergy.compas.sct.commons.scl.SclElementAdapter;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.util.MonitoringLnClassEnum;
import org.lfenergy.compas.sct.commons.util.ServicesConfigEnum;
import org.lfenergy.compas.sct.commons.util.Utils;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Stream;

import static org.lfenergy.compas.sct.commons.scl.ied.InputsAdapter.filterDuplicatedExtRefs;

/**
* A representation of the model object
* <em><b>{@link org.lfenergy.compas.scl2007b4.model.TIED IED}</b></em>.
Expand Down Expand Up @@ -62,6 +62,9 @@
public class IEDAdapter extends SclElementAdapter<SclRootAdapter, TIED> {

private static final String MESSAGE_LDEVICE_INST_NOT_FOUND = "LDevice.inst '%s' not found in IED '%s'";
private static final String DO_GOCBREF = "GoCBRef";
private static final String DO_SVCBREF = "SvCBRef";
private static final String LDSUIED_LDINST = "LDSUIED";

/**
* Constructor
Expand Down Expand Up @@ -91,10 +94,10 @@ public IEDAdapter(SclRootAdapter parentAdapter, TIED currentElem) {
public IEDAdapter(SclRootAdapter parentAdapter, String iedName) throws ScdException {
super(parentAdapter);
TIED ied = parentAdapter.getCurrentElem().getIED()
.stream()
.filter(tied -> tied.getName().equals(iedName))
.findFirst()
.orElseThrow(() -> new ScdException("Unknown IED name :" + iedName));
.stream()
.filter(tied -> tied.getName().equals(iedName))
.findFirst()
.orElseThrow(() -> new ScdException("Unknown IED name :" + iedName));
setCurrentElem(ied);
}

Expand Down Expand Up @@ -326,47 +329,50 @@ public Optional<TCompasBay> getPrivateCompasBay() {

/**
* Checks if Controls, DataSets and FCDAs of IED respect config limitation
*
* @return empty list if all IED respect limits, otherwise list of errors
*/
public List<SclReportItem> checkDataGroupCoherence() {
return streamAccessPointAdapters()
.flatMap(accessPointAdapter ->
Stream.concat(
accessPointAdapter.checkFCDALimitations().stream(),
Stream.of(
accessPointAdapter.checkControlsLimitation(ServicesConfigEnum.DATASET),
accessPointAdapter.checkControlsLimitation(ServicesConfigEnum.REPORT),
accessPointAdapter.checkControlsLimitation(ServicesConfigEnum.GSE),
accessPointAdapter.checkControlsLimitation(ServicesConfigEnum.SMV))
.flatMap(Optional::stream)
accessPointAdapter.checkFCDALimitations().stream(),
Stream.of(
accessPointAdapter.checkControlsLimitation(ServicesConfigEnum.DATASET),
accessPointAdapter.checkControlsLimitation(ServicesConfigEnum.REPORT),
accessPointAdapter.checkControlsLimitation(ServicesConfigEnum.GSE),
accessPointAdapter.checkControlsLimitation(ServicesConfigEnum.SMV))
.flatMap(Optional::stream)
)
)
.toList();
}

/**
* Checks if Controls and FCDAs of source IEDs respect config limitation
*
* @return empty list if all IED respect limits, otherwise list of errors
*/
public List<SclReportItem> checkBindingDataGroupCoherence() {
return streamAccessPointAdapters()
return streamAccessPointAdapters()
.flatMap(accessPointAdapter -> {
AccessPointAdapter.ExtRefAnalyzeRecord extRefAnalyzeRecord = accessPointAdapter.getAllCoherentExtRefForAnalyze();
return Stream.of(
extRefAnalyzeRecord.sclReportItems().stream(),
accessPointAdapter.checkLimitationForBoundIedFcdas(extRefAnalyzeRecord.tExtRefs()).stream(),
accessPointAdapter.checkLimitationForBoundIEDControls(extRefAnalyzeRecord.tExtRefs()).stream())
.flatMap(Function.identity());
extRefAnalyzeRecord.sclReportItems().stream(),
accessPointAdapter.checkLimitationForBoundIedFcdas(extRefAnalyzeRecord.tExtRefs()).stream(),
accessPointAdapter.checkLimitationForBoundIEDControls(extRefAnalyzeRecord.tExtRefs()).stream())
.flatMap(Function.identity());
}).toList();
}

private Stream<AccessPointAdapter> streamAccessPointAdapters() {
return currentElem.getAccessPoint().stream()
.map(tAccessPoint -> new AccessPointAdapter(this, tAccessPoint));
.map(tAccessPoint -> new AccessPointAdapter(this, tAccessPoint));
}

/**
* Get value of private type COMPAS-ICDHeader
*
* @return COMPAS-ICDHeader private value if present, else empty Optional
*/
public Optional<TCompasICDHeader> getCompasICDHeader() {
Expand All @@ -375,10 +381,40 @@ public Optional<TCompasICDHeader> getCompasICDHeader() {

/**
* Get value of private type COMPAS-SystemVersion
*
* @return COMPAS-SystemVersion private value if present, else empty Optional
*/
public Optional<TCompasSystemVersion> getCompasSystemVersion() {
return PrivateService.extractCompasPrivate(currentElem, TCompasSystemVersion.class);
}

/**
* Update and/or create Monitoring LNs (LSVS and LGOS) into LDSUIED for each bound ExtRef of each LDevice
*
* @return a list of SclReport Objects that contains errors
*/
public List<SclReportItem> manageMonitoringLns() {
List<SclReportItem> sclReportItems = new ArrayList<>();
findLDeviceAdapterByLdInst(LDSUIED_LDINST).ifPresent(lDeviceAdapter -> {
lDeviceAdapter.manageMonitoringLns(retrieveAllExtRefForServiceType(TServiceType.GOOSE), DO_GOCBREF, MonitoringLnClassEnum.LGOS)
.ifPresent(sclReportItems::add);
lDeviceAdapter.manageMonitoringLns(retrieveAllExtRefForServiceType(TServiceType.SMV), DO_SVCBREF, MonitoringLnClassEnum.LSVS)
.ifPresent(sclReportItems::add);
});
return sclReportItems;
}

private List<TExtRef> retrieveAllExtRefForServiceType(TServiceType tServiceType) {
return streamLDeviceAdapters()
.map(LDeviceAdapter::getLN0Adapter)
.filter(AbstractLNAdapter::hasInputs)
.map(LN0Adapter::getInputsAdapter)
.map(inputsAdapter -> filterDuplicatedExtRefs(inputsAdapter.getCurrentElem().getExtRef()))
.flatMap(List::stream)
.filter(tExtRef -> tExtRef.isSetServiceType() && tExtRef.isSetSrcCBName() &&
tServiceType.equals(tExtRef.getServiceType()))
.toList();
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import static org.lfenergy.compas.sct.commons.util.LDeviceStatus.OFF;
import static org.lfenergy.compas.sct.commons.util.LDeviceStatus.ON;
import static org.lfenergy.compas.sct.commons.util.Utils.isExtRefFeedBySameControlBlock;

/**
* A representation of the model object
Expand Down Expand Up @@ -421,4 +422,19 @@ private SclRootAdapter getSclRootAdapter() {
return getIedAdapter().getParentAdapter();
}

/**
* Remove ExtRef which are fed by same Control Block
*
* @param tExtRefs List of ExtRef
* @return list ExtRefs without duplication
*/
public static List<TExtRef> filterDuplicatedExtRefs(List<TExtRef> tExtRefs) {
List<TExtRef> filteredList = new ArrayList<>();
tExtRefs.forEach(tExtRef -> {
if (filteredList.stream().noneMatch(t -> isExtRefFeedBySameControlBlock(tExtRef, t)))
filteredList.add(tExtRef);
});
return filteredList;
}

}
Loading

0 comments on commit 5f759ed

Please sign in to comment.