Skip to content

Commit

Permalink
feat(#373): remove restriction on AccessPoint name
Browse files Browse the repository at this point in the history
Signed-off-by: Samir Romdhani <samir.romdhani@rte-france.com>
  • Loading branch information
samirromdhani committed Jan 17, 2024
1 parent aea5dd9 commit c747497
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public SCL createSCD(@NonNull SCL ssd, @NonNull HeaderDTO headerDTO, List<SCL> s
sclEditor.addHistoryItem(scd, hItem.getWho(), hItem.getWhat(), hItem.getWhy());
}
substationEditor.addSubstation(scd, ssd);
sclEditor.importSTDElementsInSCD(scd, stds, SUB_NETWORK_TYPES);
sclEditor.importSTDElementsInSCD(scd, stds);
controlBlockEditor.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scd);
return scd;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void createSCD_without_headerHistory_should_return_generatedSCD() throws Invocat
verify(sclEditor, times(1)).initScl(headerDTO.getId(), headerDTO.getVersion(), headerDTO.getRevision());
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)).importSTDElementsInSCD(any(SCL.class), anyList());
verify(controlBlockEditor, times(1)).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class));
}

Expand Down Expand Up @@ -112,7 +112,7 @@ void createSCD_with_headerHistory_should_return_generatedSCD() throws Invocation
verify(sclEditor, times(1)).initScl(headerDTO.getId(), headerDTO.getVersion(), headerDTO.getRevision());
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)).importSTDElementsInSCD(any(SCL.class), anyList());
verify(controlBlockEditor, times(1)).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class));
}

Expand Down Expand Up @@ -167,7 +167,7 @@ void createSCD_when_sclEditor_importSTDElementsInSCD_Fail_should_throw_exception
doNothing().when(sclEditor).addHistoryItem(any(SCL.class), any(), any(), any());
doNothing().when(substationEditor).addSubstation(any(SCL.class), any(SCL.class));
doThrow(new ScdException("importSTDElementsInSCD fail"))
.when(sclEditor).importSTDElementsInSCD(any(SCL.class), anyList(), anyList());
.when(sclEditor).importSTDElementsInSCD(any(SCL.class), anyList());
// When Then
assertThatThrownBy(() -> sclAutomationService.createSCD(ssd, headerDTO, List.of(std)))
.isInstanceOf(ScdException.class)
Expand All @@ -183,7 +183,7 @@ void createSCD_when_controlBlockEditor_removeAllControlBlocksAndDatasetsAndExtRe
when(sclEditor.initScl(any(UUID.class), anyString(), anyString())).thenReturn((SCL) BeanUtils.cloneBean(scl));
doNothing().when(sclEditor).addHistoryItem(any(SCL.class), any(), any(), any());
doNothing().when(substationEditor).addSubstation(any(SCL.class), any(SCL.class));
doNothing().when(sclEditor).importSTDElementsInSCD(any(SCL.class), anyList(), anyList());
doNothing().when(sclEditor).importSTDElementsInSCD(any(SCL.class), anyList());
doThrow(new ScdException("removeAllControlBlocksAndDatasetsAndExtRefSrcBindings fail"))
.when(controlBlockEditor).removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(any(SCL.class));
// When Then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,58 @@ public void addSubnetworks(SCL scd, List<SubNetworkDTO> subNetworks, SCL icd) th
}
}

@Override
public void addSubnetworks(SCL scd, SCL std, String iedName) throws ScdException {
Optional.ofNullable(std.getCommunication()).ifPresent(tCommunication ->
tCommunication.getSubNetwork().forEach(icdSubNetwork ->
icdSubNetwork.getConnectedAP().forEach(icdConnectedAP -> {
// verify if SCD/IED/ConnectedAP/apName equal to STD/Communication/SubNetwork/ConnectedAP/apName
if (scd.getIED().stream().filter(ied -> Objects.equals(ied.getName(), iedName))
.flatMap(tied -> tied.getAccessPoint().stream())
.noneMatch(tAccessPoint -> tAccessPoint.getName().equals(icdConnectedAP.getApName()))) {
throw new ScdException("Unknown AccessPoint :" + icdConnectedAP.getApName() + " in IED :" + iedName);
}
// add SubNetwork if not exist
if(scd.getCommunication() == null) {
scd.setCommunication(new TCommunication());
}
TSubNetwork tSubNetwork = scd.getCommunication().getSubNetwork()
.stream()
.filter(subNetwork -> subNetwork.getName().equals(icdSubNetwork.getName()))
.findFirst()
.orElseGet(() -> {
TSubNetwork newSubNetwork = new TSubNetwork();
newSubNetwork.setName(icdSubNetwork.getName());
newSubNetwork.setType(icdSubNetwork.getType());
scd.getCommunication().getSubNetwork().add(newSubNetwork);
return newSubNetwork;
});
// add ConnectedAP to SubNetwork if not exist
String apName = icdConnectedAP.getApName();
TConnectedAP tConnectedAP = tSubNetwork.getConnectedAP().stream()
.filter(connectedAP -> Objects.equals(connectedAP.getIedName(), iedName)
&& Objects.equals(connectedAP.getApName(), apName))
.findFirst()
.orElseGet(() -> {
TConnectedAP newConnectedAP = new TConnectedAP();
newConnectedAP.setIedName(iedName);
newConnectedAP.setApName(apName);
tSubNetwork.getConnectedAP().add(newConnectedAP);
return newConnectedAP;
});
//copy Address And PhysConn From Icd to Scd
std.getCommunication().getSubNetwork().stream()
.flatMap(subNetwork -> subNetwork.getConnectedAP().stream())
.filter(connectedAP -> connectedAP.getApName().equals(tConnectedAP.getApName()))
.findFirst()
.ifPresent(connectedAP -> {
Optional.ofNullable(connectedAP.getAddress()).ifPresent(tConnectedAP::setAddress);
tConnectedAP.getPhysConn().addAll(connectedAP.getPhysConn());
});
}))
);
}

@Override
public void updateDAI(SCL scd, String iedName, String ldInst, DataAttributeRef dataAttributeRef) throws ScdException {
long startTime = System.nanoTime();
Expand Down Expand Up @@ -139,7 +191,7 @@ public void updateDAI(SCL scd, String iedName, String ldInst, DataAttributeRef d
}

@Override
public void importSTDElementsInSCD(SCL scd, List<SCL> stds, List<SubNetworkTypeDTO> subNetworkTypes) throws ScdException {
public void importSTDElementsInSCD(SCL scd, List<SCL> stds) throws ScdException {

//Check SCD and STD compatibilities
Map<String, PrivateLinkedToStds> mapICDSystemVersionUuidAndSTDFile = PrivateUtils.createMapICDSystemVersionUuidAndSTDFile(stds);
Expand Down Expand Up @@ -167,9 +219,7 @@ public void importSTDElementsInSCD(SCL scd, List<SCL> stds, List<SubNetworkTypeD
scdRootAdapter.addIED(std, iedName);

//import connectedAP and rename ConnectedAP/@iedName
TCommunication communication = stdRootAdapter.getCurrentElem().getCommunication();
List<SubNetworkDTO> subNetworkDTOSet = SubNetworkDTO.createDefaultSubnetwork(iedName, communication, subNetworkTypes);
addSubnetworks(scdRootAdapter.getCurrentElem(), subNetworkDTOSet, std);
addSubnetworks(scdRootAdapter.getCurrentElem(), std, iedName);
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ public interface SclEditor {
*/
void addSubnetworks(SCL scd, List<SubNetworkDTO> subNetworks, SCL icd) throws ScdException;

/**
* Add or update SubNetworks in SCL file from ICD file and rename ConnectedAP/@iedName
* @param scd SCL file in which SubNetworks should be added
* @param std STD file from which SubNetworks functional data are copied from
* @param stdIedName Ied Name
*/
void addSubnetworks(SCL scd, SCL std, String stdIedName) throws ScdException;

/**
* Updates DAI based on given data in <em>dataAttributeRef</em>
*
Expand Down Expand Up @@ -118,7 +126,6 @@ public interface SclEditor {
*
* @param scd SCL object in which content of STD files are imported
* @param stds list of STD files contenting datas to import into SCD
* @param subNetworkTypes couple of Subnetwork name and possible corresponding ConnectedAP names
* @throws ScdException throws when inconsistency between Substation of SCL content and gien STD files as :
* <ul>
* <li>ICD_SYSTEM_VERSION_UUID in IED/Private of STD is not present in COMPAS-ICDHeader in Substation/../LNode of SCL</li>
Expand All @@ -128,7 +135,7 @@ public interface SclEditor {
* <li>COMPAS_ICDHEADER in Substation/../LNode of SCL not found in IED/Private of STD</li>
* </ul>
*/
void importSTDElementsInSCD(SCL scd, List<SCL> stds, List<SubNetworkTypeDTO> subNetworkTypes) throws ScdException;
void importSTDElementsInSCD(SCL scd, List<SCL> stds) throws ScdException;

/**
* Activate used LDevice and Deactivate unused LDevice in {@link TLNode <em><b>TLNode </b></em>}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@
import org.lfenergy.compas.sct.commons.scl.ln.LNAdapter;
import org.lfenergy.compas.sct.commons.testhelpers.MarshallerWrapper;
import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller;
import org.lfenergy.compas.sct.commons.scl.ied.*;
import org.lfenergy.compas.sct.commons.testhelpers.*;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;

Expand Down Expand Up @@ -174,6 +172,91 @@ void addSubnetworks_whenNoCommunicationTagInIcd_should_not_add_subnetwork() {
assertThat(marshalledScd).doesNotContain("<Communication");
}

@Test
void addSubnetworks_shouldNotUpdateScd_when_noCommunicationInICDExist() {
//Givens
SCL scd = SclTestMarshaller.getSCLFromFile("/scl_update_communication/scd_without_communication.xml");
SCL icd = SclTestMarshaller.getSCLFromFile("/scl_update_communication/std_without_communication.xml");
assertThat(scd.getCommunication()).isNull();
//When
//Then
assertThatCode(() -> sclService.addSubnetworks(scd, icd, "IED_NAME1")).doesNotThrowAnyException();
String marshalledScd = assertIsMarshallable(scd);
assertThat(scd.getCommunication()).isNull();
assertThat(marshalledScd).doesNotContain("<Communication");
assertIsMarshallable(scd);
}

@Test
void addSubnetworks_shouldAddSubNetwork_and_ConnectedAp_and_updateConnectedApIEDName() {
//Given
SCL scd = SclTestMarshaller.getSCLFromFile("/scl_update_communication/scd_without_communication.xml");
SCL std = SclTestMarshaller.getSCLFromFile("/scl_update_communication/std_with_communication.xml");
assertThat(scd.getCommunication()).isNull();
//When
//Then
assertThatCode(() -> sclService.addSubnetworks(scd, std, "IED_NAME1")).doesNotThrowAnyException();
assertThat(scd.getCommunication()).isNotNull();
String marshalledScd = assertIsMarshallable(scd);
assertThat(marshalledScd).contains("<Communication");
// assertion succeeds as subNetwork.connectedAP.iedName field is ignored.
assertThat(scd.getCommunication())
.usingRecursiveComparison()
.ignoringFields("subNetwork.connectedAP.iedName")
.isEqualTo(std.getCommunication());
assertThat(scd.getCommunication().getSubNetwork().get(0).getConnectedAP().get(0).getIedName())
.isEqualTo("IED_NAME1");
assertIsMarshallable(scd);
}


@Test
void addSubnetworks_shouldCopyAddressAndPhysConnFromIcd() {
//Givens
SCL scd = SclTestMarshaller.getSCLFromFile("/scl_update_communication/scd_without_communication.xml");
SCL std = SclTestMarshaller.getSCLFromFile("/scl_update_communication/std_with_full_filled_communication.xml");
assertThat(scd.getCommunication()).isNull();
//When
//Then
assertThatCode(() -> sclService.addSubnetworks(scd, std, "IED_NAME1")).doesNotThrowAnyException();
assertThat(scd.getCommunication()).isNotNull();
// assertion succeeds as subNetwork.connectedAP.iedName and subNetwork.connectedAP.gse fields are ignored.
// Only subNetwork.connectedAP.address and subNetwork.connectedAP.physConn added: see https://github.com/com-pas/compas-sct/issues/76
assertThat(scd.getCommunication())
.usingRecursiveComparison()
.ignoringFields("subNetwork.connectedAP.iedName", "subNetwork.connectedAP.gse")
.isEqualTo(std.getCommunication());
assertIsMarshallable(scd);
}

@Test
void addSubnetworks_shouldDoNothing_when_subNetworkAlreadyExist() {
//Givens
SCL scd = SclTestMarshaller.getSCLFromFile("/scl_update_communication/scd_without_communication.xml");
SCL std = SclTestMarshaller.getSCLFromFile("/scl_update_communication/std_with_communication.xml");
std.getCommunication().getSubNetwork().get(0).getConnectedAP().get(0).getPhysConn().clear();
std.getCommunication().getSubNetwork().get(0).getConnectedAP().get(0).setAddress(null);
std.getCommunication().getSubNetwork().get(0).getConnectedAP().get(0).unsetGSE();
//When
//Then
assertThatCode(() -> sclService.addSubnetworks(scd, std, "IED_NAME1")).doesNotThrowAnyException();
String marshalledScd = assertIsMarshallable(scd);
assertThat(marshalledScd).contains("<Communication");
}

@Test
void addSubnetworks_shouldThrowError_When_IedNameNotExistInScd() {
//Givens
SCL scd = SclTestMarshaller.getSCLFromFile("/scl_update_communication/scd_without_communication.xml");
SCL icd = SclTestMarshaller.getSCLFromFile("/scl_update_communication/std_with_communication.xml");
//When
//Then
assertThatCode(() -> sclService.addSubnetworks(scd, icd, "UnknownIedName"))
.isInstanceOf(ScdException.class)
.hasMessage("Unknown AccessPoint :ConnectedAP_Name in IED :UnknownIedName");
assertIsMarshallable(scd);
}

@Test
void testInitScl_With_headerId_shouldNotThrowError() {
//Given
Expand Down Expand Up @@ -240,7 +323,7 @@ void testImportSTDElementsInSCD_whenCalledWithOneSTD_shouldNotThrowException() {
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd.xml");
SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml");
//When Then
assertThatCode(() -> sclService.importSTDElementsInSCD(scd, List.of(std), DTO.SUB_NETWORK_TYPES))
assertThatCode(() -> sclService.importSTDElementsInSCD(scd, List.of(std)))
.doesNotThrowAnyException();
assertThat(scd.getIED()).hasSize(1);
assertThat(scd.getDataTypeTemplates()).hasNoNullFieldsOrProperties();
Expand All @@ -256,7 +339,7 @@ void importSTDElementsInSCD_whenCalledWithMultipleSTD_shouldNotThrowException()
SCL std1 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_SITESITE1SCU1.xml");
SCL std2 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_SITESITE1SCU2.xml");
//When Then
assertThatCode(() -> sclService.importSTDElementsInSCD(scd, List.of(std0, std1, std2), DTO.SUB_NETWORK_TYPES))
assertThatCode(() -> sclService.importSTDElementsInSCD(scd, List.of(std0, std1, std2)))
.doesNotThrowAnyException();
assertThat(scd.getIED()).hasSize(3);
assertThat(scd.getDataTypeTemplates()).hasNoNullFieldsOrProperties();
Expand All @@ -274,7 +357,7 @@ void importSTDElementsInSCD_whenManySTDMatchCompasICDHeader_shouldThrowException
SCL std2 = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml");
List<SCL> stds = List.of(std1, std2);
//When Then
assertThatThrownBy(() -> sclService.importSTDElementsInSCD(scd, stds, DTO.SUB_NETWORK_TYPES))
assertThatThrownBy(() -> sclService.importSTDElementsInSCD(scd, stds))
.isInstanceOf(ScdException.class);
assertIsMarshallable(scd);
}
Expand All @@ -285,7 +368,7 @@ void importSTDElementsInSCD_whenSCDFileContainsSameICDHeaderInTwoDifferentFuncti
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/scd_with_same_compas_icd_header_in_different_functions.xml");
SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std.xml");
//When Then
assertThatCode(() -> sclService.importSTDElementsInSCD(scd, List.of(std), DTO.SUB_NETWORK_TYPES)).doesNotThrowAnyException();
assertThatCode(() -> sclService.importSTDElementsInSCD(scd, List.of(std))).doesNotThrowAnyException();
assertIsMarshallable(scd);
}

Expand All @@ -296,7 +379,7 @@ void importSTDElementsInSCD_whenCompasICDHeaderNotMatch__shouldThrowException()
SCL std = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/std_with_same_ICDSystemVersionUUID.xml");
List<SCL> stdList = List.of(std);
//When Then
assertThatThrownBy(() -> sclService.importSTDElementsInSCD(scd, stdList, DTO.SUB_NETWORK_TYPES))
assertThatThrownBy(() -> sclService.importSTDElementsInSCD(scd, stdList))
.isInstanceOf(ScdException.class)
.hasMessageContaining("COMPAS-ICDHeader is not the same in Substation and in IED");
assertIsMarshallable(scd);
Expand All @@ -308,7 +391,7 @@ void importSTDElementsInSCD_whenNoSTDMatch_shouldThrowException() {
SCL scd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/ssd.xml");
List<SCL> stdList = List.of();
//When Then
assertThatCode(() -> sclService.importSTDElementsInSCD(scd, stdList, DTO.SUB_NETWORK_TYPES))
assertThatCode(() -> sclService.importSTDElementsInSCD(scd, stdList))
.isInstanceOf(ScdException.class)
.hasMessage("There is no STD file found corresponding to headerId = f8dbc8c1-2db7-4652-a9d6-0b414bdeccfa, headerVersion = 01.00.00, headerRevision = 01.00.00 and ICDSystemVersionUUID = IED4d4fe1a8cda64cf88a5ee4176a1a0eef");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import org.lfenergy.compas.scl2007b4.model.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;

public class DTO {
Expand Down Expand Up @@ -301,7 +300,4 @@ public static HeaderDTO.HistoryItem createHeaderItem(String now) {
return historyItem;
}

public static final List<SubNetworkTypeDTO> SUB_NETWORK_TYPES = List.of(
new SubNetworkTypeDTO("RSPACE_PROCESS_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString(), List.of("PROCESS_AP", "TOTO_AP_GE")),
new SubNetworkTypeDTO("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString(), List.of("ADMIN_AP", "TATA_AP_EFFACEC")));
}
Loading

0 comments on commit c747497

Please sign in to comment.