Skip to content

Commit

Permalink
Merge pull request #330 from com-pas/refactor/329-rsr-681-refactor-an…
Browse files Browse the repository at this point in the history
…d-restruct-extrefservice

Refactor/329 RSR 681 refactor and restruct extrefservice, fix #329
  • Loading branch information
samirromdhani authored Nov 13, 2023
2 parents ce70880 + c09e89f commit f5e7098
Show file tree
Hide file tree
Showing 12 changed files with 824 additions and 713 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.sct.commons.api.ControlBlockEditor;
import org.lfenergy.compas.sct.commons.api.SclEditor;
import org.lfenergy.compas.sct.commons.api.SubstationEditor;
import org.lfenergy.compas.sct.commons.dto.HeaderDTO;
Expand All @@ -30,6 +31,7 @@ public class SclAutomationService {

private final SclEditor sclEditor;
private final SubstationEditor substationEditor;
private final ControlBlockEditor controlBlockEditor;

/**
* Possible Subnetwork and ConnectedAP names which should be used in generated SCD in order a have global coherence
Expand All @@ -56,7 +58,7 @@ public SCL createSCD(@NonNull SCL ssd, @NonNull HeaderDTO headerDTO, List<SCL> s
}
substationEditor.addSubstation(scd, ssd);
sclEditor.importSTDElementsInSCD(scd, stds, SUB_NETWORK_TYPES);
sclEditor.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scd);
controlBlockEditor.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scd);
return scd;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
import org.junit.jupiter.api.Test;
import org.lfenergy.compas.scl2007b4.model.LN0;
import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.sct.commons.SclEditorService;
import org.lfenergy.compas.sct.commons.ControlBlockService;
import org.lfenergy.compas.sct.commons.SclService;
import org.lfenergy.compas.sct.commons.SubstationService;
import org.lfenergy.compas.sct.commons.api.ControlBlockEditor;
import org.lfenergy.compas.sct.commons.api.SclEditor;
import org.lfenergy.compas.sct.commons.api.SubstationEditor;
import org.lfenergy.compas.sct.commons.dto.HeaderDTO;
Expand All @@ -29,8 +31,9 @@
class SclAutomationServiceIntegrationTest {

private SclAutomationService sclAutomationService ;
private static final SclEditor sclEditor = new SclEditorService() ;
private static final SclEditor sclEditor = new SclService() ;
private static final SubstationEditor substationEditor = new SubstationService() ;
private static final ControlBlockEditor controlBlockEditor = new ControlBlockService() ;

private HeaderDTO headerDTO;

Expand All @@ -40,7 +43,7 @@ void setUp() {
headerDTO.setId(UUID.randomUUID());
headerDTO.setRevision("hRevision");
headerDTO.setVersion("hVersion");
sclAutomationService = new SclAutomationService(sclEditor, substationEditor);
sclAutomationService = new SclAutomationService(sclEditor, substationEditor, controlBlockEditor);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.lfenergy.compas.scl2007b4.model.SCL;
import org.lfenergy.compas.scl2007b4.model.THeader;
import org.lfenergy.compas.sct.commons.api.ControlBlockEditor;
import org.lfenergy.compas.sct.commons.api.SclEditor;
import org.lfenergy.compas.sct.commons.api.SubstationEditor;
import org.lfenergy.compas.sct.commons.dto.HeaderDTO;
Expand Down Expand Up @@ -39,6 +40,8 @@ class SclAutomationServiceTest {
private SclEditor sclEditor;
@Mock
private SubstationEditor substationEditor;
@Mock
private ControlBlockEditor controlBlockEditor;

public static final short RELEASE = 4;
public static final String REVISION = "B";
Expand Down Expand Up @@ -81,7 +84,7 @@ void createSCD_without_headerHistory_should_return_generatedSCD() throws Invocat
verify(sclEditor, times(0)).addHistoryItem(any(SCL.class), anyString(), anyString(), anyString());
verify(substationEditor, times(1)).addSubstation(any(SCL.class), any(SCL.class));
verify(sclEditor, times(1)).importSTDElementsInSCD(any(SCL.class), anyList(), anyList());
verify(sclEditor, times(1)).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class));
verify(controlBlockEditor, times(1)).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class));
}

@Test
Expand Down Expand Up @@ -110,7 +113,7 @@ void createSCD_with_headerHistory_should_return_generatedSCD() throws Invocation
verify(sclEditor, times(1)).addHistoryItem(any(SCL.class), eq(historyItem.getWho()), eq(historyItem.getWhat()), eq(historyItem.getWhy()));
verify(substationEditor, times(1)).addSubstation(any(SCL.class), any(SCL.class));
verify(sclEditor, times(1)).importSTDElementsInSCD(any(SCL.class), anyList(), anyList());
verify(sclEditor, times(1)).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class));
verify(controlBlockEditor, times(1)).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class));
}

@Test
Expand Down Expand Up @@ -172,7 +175,7 @@ void createSCD_when_sclEditor_importSTDElementsInSCD_Fail_should_throw_exception
}

@Test
void createSCD_when_sclEditor_removeAllControlBlocksAndDatasetsAndExtRefSrcBindings_Fail_should_throw_exception() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
void createSCD_when_controlBlockEditor_removeAllControlBlocksAndDatasetsAndExtRefSrcBindings_Fail_should_throw_exception() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException {
// Given
SCL ssd = (SCL) BeanUtils.cloneBean(scl);
SCL std = (SCL) BeanUtils.cloneBean(scl);
Expand All @@ -182,7 +185,7 @@ void createSCD_when_sclEditor_removeAllControlBlocksAndDatasetsAndExtRefSrcBindi
doNothing().when(substationEditor).addSubstation(any(SCL.class), any(SCL.class));
doNothing().when(sclEditor).importSTDElementsInSCD(any(SCL.class), anyList(), anyList());
doThrow(new ScdException("removeAllControlBlocksAndDatasetsAndExtRefSrcBindings fail"))
.when(sclEditor).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class));
.when(controlBlockEditor).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class));
// When Then
assertThatThrownBy(() -> sclAutomationService.createSCD(ssd, headerDTO, List.of(std)))
.isInstanceOf(ScdException.class)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// SPDX-FileCopyrightText: 2022 2023 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.*;
import org.lfenergy.compas.sct.commons.api.ControlBlockEditor;
import org.lfenergy.compas.sct.commons.dto.*;
import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.NetworkRanges;
import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.RangesPerCbType;
import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.Settings;
import org.lfenergy.compas.sct.commons.dto.ControlBlockNetworkSettings.SettingsOrError;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.*;
import org.lfenergy.compas.sct.commons.util.*;

import java.util.*;
import java.util.stream.Stream;

public class ControlBlockService implements ControlBlockEditor {


@Override
public List<SclReportItem> analyzeDataGroups(SCL scd) {
SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
return sclRootAdapter.streamIEDAdapters()
.map(iedAdapter -> {
List<SclReportItem> list = new ArrayList<>();
list.addAll(iedAdapter.checkDataGroupCoherence());
list.addAll(iedAdapter.checkBindingDataGroupCoherence());
return list;
}).flatMap(Collection::stream).toList();
}

@Override
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, allowedFcdas);
}

@Override
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(), allowedFcdas);

}

@Override
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), allowedFcdas);
}

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 -> lDeviceAdapter.createDataSetAndControlBlocks(allowedFcdas))
.flatMap(List::stream)
.toList();
}

@Override
public List<SclReportItem> configureNetworkForAllControlBlocks(SCL scd, ControlBlockNetworkSettings controlBlockNetworkSettings,
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));
return sclReportItems;
}

@Override
public void removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(final SCL scl) {
SclRootAdapter sclRootAdapter = new SclRootAdapter(scl);
List<LDeviceAdapter> lDeviceAdapters = sclRootAdapter.streamIEDAdapters()
.flatMap(IEDAdapter::streamLDeviceAdapters).toList();
// LN0
lDeviceAdapters.stream()
.map(LDeviceAdapter::getLN0Adapter)
.forEach(ln0 -> {
ln0.removeAllControlBlocksAndDatasets();
ln0.removeAllExtRefSourceBindings();
});
// Other LN
lDeviceAdapters.stream()
.map(LDeviceAdapter::getLNAdapters).flatMap(List::stream)
.forEach(LNAdapter::removeAllControlBlocksAndDatasets);
}


private List<SclReportItem> configureNetworkForControlBlocks(SCL scd, ControlBlockNetworkSettings controlBlockNetworkSettings,
NetworkRanges networkRanges, ControlBlockEnum controlBlockEnum) {
PrimitiveIterator.OfLong appIdIterator = Utils.sequence(networkRanges.appIdStart(), networkRanges.appIdEnd());
Iterator<String> macAddressIterator = Utils.macAddressSequence(networkRanges.macAddressStart(), networkRanges.macAddressEnd());

SclRootAdapter sclRootAdapter = new SclRootAdapter(scd);
return sclRootAdapter.streamIEDAdapters()
.flatMap(iedAdapter ->
iedAdapter.streamLDeviceAdapters()
.filter(LDeviceAdapter::hasLN0)
.map(LDeviceAdapter::getLN0Adapter)
.flatMap(ln0Adapter -> ln0Adapter.streamControlBlocks(controlBlockEnum))
.map(controlBlockAdapter -> configureControlBlockNetwork(controlBlockNetworkSettings, appIdIterator, macAddressIterator, controlBlockAdapter)))
.flatMap(Optional::stream)
.toList();
}

private Optional<SclReportItem> configureControlBlockNetwork(ControlBlockNetworkSettings controlBlockNetworkSettings, PrimitiveIterator.OfLong appIdIterator, Iterator<String> macAddressIterator, ControlBlockAdapter controlBlockAdapter) {
SettingsOrError settingsOrError = controlBlockNetworkSettings.getNetworkSettings(controlBlockAdapter);
if (settingsOrError.errorMessage() != null) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
"Cannot configure network for this ControlBlock because: " + settingsOrError.errorMessage()));
}
Settings settings = settingsOrError.settings();
if (settings == null) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
"Cannot configure network for this ControlBlock because no settings was provided"));
}
if (settings.vlanId() == null) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
"Cannot configure network for this ControlBlock because no Vlan Id was provided in the settings"));
}
if (!appIdIterator.hasNext()) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
"Cannot configure network for this ControlBlock because range of appId is exhausted"));
}
if (!macAddressIterator.hasNext()) {
return Optional.of(controlBlockAdapter.buildFatalReportItem(
"Cannot configure network for this ControlBlock because range of MAC Address is exhausted"));
}

return controlBlockAdapter.configureNetwork(appIdIterator.nextLong(), macAddressIterator.next(), settings.vlanId(), settings.vlanPriority(),
settings.minTime(), settings.maxTime());
}

}
Loading

0 comments on commit f5e7098

Please sign in to comment.