Skip to content

Commit

Permalink
feat(#332): move FCDA parameter csv file management out of compas
Browse files Browse the repository at this point in the history
Signed-off-by: Aliou DIAITE <[email protected]>
  • Loading branch information
AliouDIAITE committed Oct 12, 2023
1 parent a68f379 commit c374dd0
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 20,457 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,41 +112,50 @@ public List<SclReportItem> updateAllExtRefIedNames(SCL scd) {
}

@Override
public List<SclReportItem> createDataSetAndControlBlocks(SCL scd) {
public List<SclReportItem> createDataSetAndControlBlocks(SCL scd, Set<FcdaForDataSetsCreation> allowedFcdas) {
checkFcdaInitDataPresence(allowedFcdas);
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
Stream<LDeviceAdapter> lDeviceAdapters = sclRootAdapter.streamIEDAdapters().flatMap(IEDAdapter::streamLDeviceAdapters);
return createDataSetAndControlBlocks(lDeviceAdapters);
return createDataSetAndControlBlocks(lDeviceAdapters, allowedFcdas);
}

@Override
public List<SclReportItem> createDataSetAndControlBlocks(SCL scd, String targetIedName) {
public List<SclReportItem> createDataSetAndControlBlocks(SCL scd, String targetIedName, Set<FcdaForDataSetsCreation> allowedFcdas) {
checkFcdaInitDataPresence(allowedFcdas);
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(targetIedName);
return createDataSetAndControlBlocks(iedAdapter.streamLDeviceAdapters());
return createDataSetAndControlBlocks(iedAdapter.streamLDeviceAdapters(), allowedFcdas);

}

@Override
public List<SclReportItem> createDataSetAndControlBlocks(SCL scd, String targetIedName, String targetLDeviceInst) {
public List<SclReportItem> createDataSetAndControlBlocks(SCL scd, String targetIedName, String targetLDeviceInst, Set<FcdaForDataSetsCreation> allowedFcdas) {
if (StringUtils.isBlank(targetIedName)) {
throw new ScdException("IED.name parameter is missing");
}
checkFcdaInitDataPresence(allowedFcdas);
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
IEDAdapter iedAdapter = sclRootAdapter.getIEDAdapterByName(targetIedName);
LDeviceAdapter lDeviceAdapter = iedAdapter.getLDeviceAdapterByLdInst(targetLDeviceInst);
return createDataSetAndControlBlocks(Stream.of(lDeviceAdapter));
return createDataSetAndControlBlocks(Stream.of(lDeviceAdapter), allowedFcdas);
}

private List<SclReportItem> createDataSetAndControlBlocks(Stream<LDeviceAdapter> lDeviceAdapters) {
private void checkFcdaInitDataPresence(Set<FcdaForDataSetsCreation> allowedFcdas) {
if (allowedFcdas == null || allowedFcdas.isEmpty()) {
throw new ScdException("Accepted FCDAs list is empty, you should initialize allowed FCDA lists with CsvHelper class before");
}
}

private List<SclReportItem> createDataSetAndControlBlocks(Stream<LDeviceAdapter> lDeviceAdapters, Set<FcdaForDataSetsCreation> allowedFcdas) {
return lDeviceAdapters
.map(LDeviceAdapter::createDataSetAndControlBlocks)
.map(lDeviceAdapter -> lDeviceAdapter.createDataSetAndControlBlocks(allowedFcdas))
.flatMap(List::stream)
.toList();
}

@Override
public List<SclReportItem> configureNetworkForAllControlBlocks(SCL scd, ControlBlockNetworkSettings controlBlockNetworkSettings,
RangesPerCbType rangesPerCbType) {
RangesPerCbType rangesPerCbType) {
List<SclReportItem> sclReportItems = new ArrayList<>();
sclReportItems.addAll(configureNetworkForControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType.gse(), ControlBlockEnum.GSE));
sclReportItems.addAll(configureNetworkForControlBlocks(scd, controlBlockNetworkSettings, rangesPerCbType.sampledValue(), ControlBlockEnum.SAMPLED_VALUE));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@

import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.scl2007b4.model.TExtRef;
import org.lfenergy.compas.sct.commons.dto.*;
import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings;
import org.lfenergy.compas.sct.commons.dto.ExtRefInfo;
import org.lfenergy.compas.sct.commons.dto.FcdaForDataSetsCreation;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.util.ILDEPFSettings;
import org.lfenergy.compas.sct.commons.util.Utils;

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

/**
* Service class that will be used to create, update or delete elements related to the {@link TExtRef <em>TExtRef</em>} object.
Expand Down Expand Up @@ -61,29 +65,32 @@ public interface ExtRefEditor {
/**
* Create All DataSet and ControlBlock in the SCL based on the ExtRef
*
* @param scd input SCD object. It could be modified by adding new DataSet and ControlBlocks
* @param scd input SCD object. It could be modified by adding new DataSet and ControlBlocks
* @param allowedFcdas List of allowed FCDA for DataSets and Control Blocks creation
* @return list of encountered errors
*/
List<SclReportItem> createDataSetAndControlBlocks(SCL scd);
List<SclReportItem> createDataSetAndControlBlocks(SCL scd, Set<FcdaForDataSetsCreation> allowedFcdas);

/**
* Create All DataSet and ControlBlock for the ExtRef in given IED
*
* @param scd input SCD object. The object will be modified with the new DataSet and ControlBlocks
* @param targetIedName the name of the IED where the ExtRef are
* @param allowedFcdas List of allowed FCDA for DataSets and Control Blocks creation
* @return list of encountered errors
*/
List<SclReportItem> createDataSetAndControlBlocks(SCL scd, String targetIedName);
List<SclReportItem> createDataSetAndControlBlocks(SCL scd, String targetIedName, Set<FcdaForDataSetsCreation> allowedFcdas);

/**
* Create All DataSet and ControlBlock for the ExtRef in given IED and LDevice
*
* @param scd input SCD object. The object will be modified with the new DataSet and ControlBlocks
* @param targetIedName the name of the IED where the ExtRef are
* @param targetLDeviceInst the name of the LDevice where the ExtRef are
* @param allowedFcdas List of allowed FCDA for DataSets and Control Blocks creation
* @return list of encountered errors
*/
List<SclReportItem> createDataSetAndControlBlocks(SCL scd, String targetIedName, String targetLDeviceInst);
List<SclReportItem> createDataSetAndControlBlocks(SCL scd, String targetIedName, String targetLDeviceInst, Set<FcdaForDataSetsCreation> allowedFcdas);

/**
* Configure the network for all the ControlBlocks.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* // SPDX-FileCopyrightText: 2023 RTE FRANCE
* //
* // SPDX-License-Identifier: Apache-2.0
*/

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

import com.opencsv.bean.CsvBindByPosition;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@EqualsAndHashCode
public class FcdaForDataSetsCreation {

@CsvBindByPosition(position = 0)
private String lnClass;
@CsvBindByPosition(position = 1)
private String doName;
@CsvBindByPosition(position = 2)
private String daName;
@CsvBindByPosition(position = 3)
private String fc;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.lfenergy.compas.scl2007b4.model.*;
import org.lfenergy.compas.sct.commons.ExtRefService;
import org.lfenergy.compas.sct.commons.dto.DataAttributeRef;
import org.lfenergy.compas.sct.commons.dto.FcdaForDataSetsCreation;
import org.lfenergy.compas.sct.commons.dto.SclReportItem;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.util.PrivateUtils;
import org.lfenergy.compas.sct.commons.scl.SclElementAdapter;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.ExtRefService;
import org.lfenergy.compas.sct.commons.util.ControlBlockEnum;
import org.lfenergy.compas.sct.commons.util.FcdaCandidates;
import org.lfenergy.compas.sct.commons.util.LdeviceStatus;
import org.lfenergy.compas.sct.commons.util.PrivateUtils;
import org.lfenergy.compas.sct.commons.util.Utils;

import java.util.*;
Expand Down Expand Up @@ -257,7 +257,7 @@ private AbstractLNAdapter<?> getLNAdapter() {
return parentAdapter;
}

public List<SclReportItem> updateAllSourceDataSetsAndControlBlocks() {
public List<SclReportItem> updateAllSourceDataSetsAndControlBlocks(Set<FcdaForDataSetsCreation> allowedFcdas) {
String currentBayUuid = getIedAdapter().getPrivateCompasBay().map(TCompasBay::getUUID).orElse(null);
if (StringUtils.isBlank(currentBayUuid)) {
return List.of(getIedAdapter().buildFatalReportItem(MESSAGE_IED_MISSING_COMPAS_BAY_UUID));
Expand All @@ -266,7 +266,7 @@ public List<SclReportItem> updateAllSourceDataSetsAndControlBlocks() {
.filter(this::areBindingAttributesPresent)
.filter(this::isExternalBound)
.filter(this::matchingCompasFlowIsActiveOrUntested)
.map(extRef -> updateSourceDataSetsAndControlBlocks(extRef, currentBayUuid))
.map(extRef -> updateSourceDataSetsAndControlBlocks(extRef, currentBayUuid, allowedFcdas))
.flatMap(Optional::stream)
.toList();
}
Expand All @@ -290,7 +290,7 @@ private boolean areBindingAttributesPresent(TExtRef tExtRef) {
&& StringUtils.isNotBlank(tExtRef.getDoName());
}

private Optional<SclReportItem> updateSourceDataSetsAndControlBlocks(TExtRef extRef, String targetBayUuid) {
private Optional<SclReportItem> updateSourceDataSetsAndControlBlocks(TExtRef extRef, String targetBayUuid, Set<FcdaForDataSetsCreation> allowedFcdas) {
if (extRef.getServiceType() == null) {
return fatalReportItem(extRef, MESSAGE_SERVICE_TYPE_MISSING);
}
Expand Down Expand Up @@ -318,7 +318,7 @@ private Optional<SclReportItem> updateSourceDataSetsAndControlBlocks(TExtRef ext
return warningReportItem(extRef, String.format(MESSAGE_SOURCE_LN_NOT_FOUND, optionalSourceLDevice.get().getXPath()));
}

Optional<SclReportItem> sclReportItem = removeFilteredSourceDas(extRef, sourceDas);
Optional<SclReportItem> sclReportItem = removeFilteredSourceDas(extRef, sourceDas, allowedFcdas);
if (sclReportItem.isPresent()) {
return sclReportItem;
}
Expand Down Expand Up @@ -381,18 +381,29 @@ private static String generateDataSetSuffix(TExtRef extRef, DataAttributeRef sou
+ (isBayInternal ? "I" : "E");
}

private Optional<SclReportItem> removeFilteredSourceDas(TExtRef extRef, final Set<DataAttributeRef> sourceDas) {
private Optional<SclReportItem> removeFilteredSourceDas(TExtRef extRef, final Set<DataAttributeRef> sourceDas, Set<FcdaForDataSetsCreation> allowedFcdas) {
sourceDas.removeIf(da -> da.getFc() != TFCEnum.MX && da.getFc() != TFCEnum.ST);
return switch (extRef.getServiceType()) {
case GOOSE, SMV -> {
sourceDas.removeIf(Predicate.not(FcdaCandidates.SINGLETON::contains));
sourceDas.removeIf(Predicate.not(dataAttributeRef -> isFcdaAllowed(dataAttributeRef, allowedFcdas)));
yield Optional.empty();
}
case REPORT -> removeFilterSourceDaForReport(extRef, sourceDas);
default -> fatalReportItem(extRef, String.format(MESSAGE_INVALID_SERVICE_TYPE, extRef.getServiceType()));
};
}

private boolean isFcdaAllowed(DataAttributeRef dataAttributeRef, Set<FcdaForDataSetsCreation> allowedFcdas) {
String lnClass = dataAttributeRef.getLnClass();
String doName = dataAttributeRef.getDoName().toStringWithoutInst();
String daName = dataAttributeRef.getDaName().toString();
String fc = dataAttributeRef.getFc().value();
if (StringUtils.isBlank(lnClass) || StringUtils.isBlank(doName) || StringUtils.isBlank(daName) || StringUtils.isBlank(fc)) {
throw new IllegalArgumentException("parameters must not be blank");
}
return allowedFcdas.contains(new FcdaForDataSetsCreation(lnClass, doName, daName, fc));
}

private Optional<SclReportItem> removeFilterSourceDaForReport(TExtRef extRef, Set<DataAttributeRef> sourceDas) {
String daName = Utils.extractField(extRef.getDesc(), ATTRIBUTE_VALUE_SEPARATOR, EXTREF_DESC_DA_NAME_POSITION);
if (StringUtils.isBlank(daName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,13 +351,13 @@ public List<AbstractLNAdapter<?>> getLNAdaptersIncludingLN0() {
return aLNAdapters;
}

public List<SclReportItem> createDataSetAndControlBlocks() {
public List<SclReportItem> createDataSetAndControlBlocks(Set<FcdaForDataSetsCreation> allowedFcdas) {
LN0Adapter ln0Adapter = getLN0Adapter();
if (!ln0Adapter.hasInputs()) {
return Collections.emptyList();
}
return ln0Adapter.getInputsAdapter()
.updateAllSourceDataSetsAndControlBlocks();
.updateAllSourceDataSetsAndControlBlocks(allowedFcdas);
}

public Set<DataAttributeRef> findSourceDA(TExtRef extRef) {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,52 @@

import com.opencsv.bean.CsvBindByPosition;
import lombok.Getter;
import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.scl2007b4.model.TFCDA;
import org.lfenergy.compas.scl2007b4.model.TFCEnum;
import org.lfenergy.compas.sct.commons.dto.FcdaForDataSetsCreation;

import java.io.Reader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* This class is a helper method to load FCDA from a CSV file for use with {@link IHmiService#createAllHmiReportControlBlocks}
* This class is a helper method to load FCDA from a CSV files for use with
* {@link org.lfenergy.compas.sct.commons.HmiService#createAllHmiReportControlBlocks(SCL, List)}
* {@link org.lfenergy.compas.sct.commons.ExtRefService#createDataSetAndControlBlocks(SCL, Set)}
* {@link org.lfenergy.compas.sct.commons.ExtRefService#createDataSetAndControlBlocks(SCL, String, Set)}
* {@link org.lfenergy.compas.sct.commons.ExtRefService#createDataSetAndControlBlocks(SCL, String, String, Set)}
* Use the getter to access the list of parsed FCDA.
*
* @see CsvUtils
* @see IHmiService#createAllHmiReportControlBlocks
*/
public class FcdaCsvHelper {

@Getter
private final List<TFCDA> fcdas;
private final List<TFCDA> fcdaForHmiReportControls;

@Getter
private final Set<FcdaForDataSetsCreation> fcdaForDataSets;

/**
* Constructor
* Provide the CSV file as a Reader. For example, you can create a reader like this :
* Provide the CSV files as a Reader. For example, you can create a reader like this :
* <code>new InputStreamReader(getClass().getClassLoader().getResourceAsStream(fileName), StandardCharsets.UTF_8);</code>
*
* @param csvSource a reader that provides the data as CSV
* @param csvSourceForHmiReportControl a reader that provides the FCDA datas for HMI ReportControl Blocks as CSV
* @param csvSourceForDataSetAndControlBlocks a reader that provides the FCDA datas for DataSets and Control Blocks creation as CSV
*/
public FcdaCsvHelper(Reader csvSource) {
fcdas = CsvUtils.parseRows(csvSource, Row.class).stream()
.map(row ->
SclConstructorHelper.newFcda(row.ldInst, row.lnClass, row.lnInst, row.prefix, row.doName, null, row.fc)
public FcdaCsvHelper(Reader csvSourceForHmiReportControl, Reader csvSourceForDataSetAndControlBlocks) {
fcdaForHmiReportControls = CsvUtils.parseRows(csvSourceForHmiReportControl, FcdaForHmiReportControl.class).stream()
.map(fcdaForHmiReportControl ->
SclConstructorHelper.newFcda(fcdaForHmiReportControl.ldInst, fcdaForHmiReportControl.lnClass, fcdaForHmiReportControl.lnInst, fcdaForHmiReportControl.prefix, fcdaForHmiReportControl.doName, null, fcdaForHmiReportControl.fc)
)
.toList();
fcdaForDataSets = new HashSet<>(CsvUtils.parseRows(csvSourceForDataSetAndControlBlocks, FcdaForDataSetsCreation.class));
}

public static class Row {
public static class FcdaForHmiReportControl {
@CsvBindByPosition(position = 0)
private String ldInst;
@CsvBindByPosition(position = 1)
Expand All @@ -54,4 +66,19 @@ public static class Row {
private TFCEnum fc;
}

/* @NoArgsConstructor
@AllArgsConstructor
@Getter
@EqualsAndHashCode
public static class FcdaForDataSets {
@CsvBindByPosition(position = 0)
private String lnClass;
@CsvBindByPosition(position = 1)
private String doName;
@CsvBindByPosition(position = 2)
private String daName;
@CsvBindByPosition(position = 3)
private String fc;
} */

}
Loading

0 comments on commit c374dd0

Please sign in to comment.