Skip to content

Commit

Permalink
Merge pull request #195 from com-pas/develop
Browse files Browse the repository at this point in the history
Merge develop into main
  • Loading branch information
AliouDIAITE authored Nov 14, 2022
2 parents 845e7bf + 742016e commit 88291aa
Show file tree
Hide file tree
Showing 31 changed files with 1,170 additions and 298 deletions.
14 changes: 14 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,20 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven.plugin.javadoc}</version>
<executions>
<execution>
<id>attach-javadocs</id>
<phase>package</phase>
<goals>
<goal>aggregate</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
Expand Down
5 changes: 5 additions & 0 deletions sct-app/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@
<version>3.6.28</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.23.1</version>
</dependency>
</dependencies>
<build>
<plugins>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ public class SclAutomationService {
*/
private static final Map<Pair<String, String>, List<String>> comMap = Map.of(
Pair.of("RSPACE_PROCESS_NETWORK", SubNetworkDTO.SubnetworkType.MMS.toString()), Arrays.asList("PROCESS_AP", "TOTO_AP_GE"),
Pair.of("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString()), Arrays.asList("ADMIN_AP","TATA_AP_EFFACEC"));
Pair.of("RSPACE_ADMIN_NETWORK", SubNetworkDTO.SubnetworkType.IP.toString()), Arrays.asList("ADMIN_AP", "TATA_AP_EFFACEC"));

private SclAutomationService(){throw new IllegalStateException("SclAutomationService class"); }
private SclAutomationService() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

/**
* Create a SCD file from specified parameters, it calls all functions defined in the process one by one, every step
Expand All @@ -48,13 +50,14 @@ public class SclAutomationService {
*/
public static SclRootAdapter createSCD(@NonNull SCL ssd, @NonNull HeaderDTO headerDTO, Set<SCL> stds) throws ScdException {
SclRootAdapter scdAdapter = SclService.initScl(Optional.ofNullable(headerDTO.getId()),
headerDTO.getVersion(),headerDTO.getRevision());
if(!headerDTO.getHistoryItems().isEmpty()) {
headerDTO.getVersion(), headerDTO.getRevision());
if (!headerDTO.getHistoryItems().isEmpty()) {
HeaderDTO.HistoryItem hItem = headerDTO.getHistoryItems().get(0);
SclService.addHistoryItem(scdAdapter.getCurrentElem(), hItem.getWho(), hItem.getWhat(), hItem.getWhy());
}
SubstationService.addSubstation(scdAdapter.getCurrentElem(), ssd);
SclService.importSTDElementsInSCD(scdAdapter, stds, comMap);
SclService.removeAllControlBlocksAndDatasetsAndExtRefSrcBindings(scdAdapter.getCurrentElem());
return scdAdapter;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,23 @@

import org.junit.jupiter.api.BeforeEach;
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.dto.HeaderDTO;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.scl.SclElementAdapter;
import org.lfenergy.compas.sct.commons.scl.SclRootAdapter;
import org.lfenergy.compas.sct.commons.scl.ied.LDeviceAdapter;
import org.lfenergy.compas.sct.commons.testhelpers.SclTestMarshaller;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

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

Expand All @@ -24,7 +31,7 @@ class SclAutomationServiceTest {
private HeaderDTO headerDTO;

@BeforeEach
void init(){
void init() {
headerDTO = new HeaderDTO();
headerDTO.setRevision("hRevision");
headerDTO.setVersion("hVersion");
Expand Down Expand Up @@ -63,7 +70,7 @@ void createSCD_With_HItem() throws Exception {
SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std1, std2, std3));
// Then
assertNotNull(expectedSCD.getCurrentElem().getHeader().getId());
assertEquals(1 ,expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size());
assertEquals(1, expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size());
assertEquals(1, expectedSCD.getCurrentElem().getSubstation().size());
assertIsMarshallable(expectedSCD.getCurrentElem());
}
Expand All @@ -85,7 +92,7 @@ void createSCD_With_HItems() throws Exception {
SCL std2 = SclTestMarshaller.getSCLFromFile("/std_2.xml");
SCL std3 = SclTestMarshaller.getSCLFromFile("/std_3.xml");
// When
SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO,Set.of(std1, std2, std3));
SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std1, std2, std3));
// Then
assertNotNull(expectedSCD.getCurrentElem().getHeader().getId());
assertEquals(1, expectedSCD.getCurrentElem().getHeader().getHistory().getHitem().size());
Expand All @@ -98,8 +105,68 @@ void createSCD_SSD_Without_Substation() throws Exception {
// Given
SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd_without_substations.xml");
// When & Then
Set<SCL> stdListEmpty = new HashSet<>();
assertThrows(ScdException.class,
() -> SclAutomationService.createSCD(ssd, headerDTO, new HashSet<>()) );
() -> SclAutomationService.createSCD(ssd, headerDTO, stdListEmpty));
}

@Test
void createSCD_should_throw_exception_when_null_ssd() throws Exception {
// Given
HeaderDTO.HistoryItem historyItem = new HeaderDTO.HistoryItem();
historyItem.setWhat("what");
historyItem.setWho("me");
historyItem.setWhy("because");
headerDTO.getHistoryItems().add(historyItem);
SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml");
Set<SCL> stdList = Set.of(std1);

// When & Then
assertThrows(NullPointerException.class, () -> SclAutomationService.createSCD(null, headerDTO, stdList));
}

@Test
void createSCD_should_throw_exception_when_null_headerDTO() throws Exception {
// Given
SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-substation-import-ssd/ssd.xml");
SCL std1 = SclTestMarshaller.getSCLFromFile("/std_1.xml");
Set<SCL> stdList = Set.of(std1);

// When & Then
assertThrows(NullPointerException.class, () -> SclAutomationService.createSCD(ssd, null, stdList));
}

@Test
void createSCD_should_delete_ControlBlocks_DataSet_and_ExtRef_src_attributes() throws Exception {
// Given
SCL ssd = SclTestMarshaller.getSCLFromFile("/scd-ied-dtt-com-import-stds/ssd.xml");
SCL std = SclTestMarshaller.getSCLFromFile("/scl-remove-controlBlocks-dataSet-extRefSrc/scl-with-control-blocks.xml");
// When
SclRootAdapter expectedSCD = SclAutomationService.createSCD(ssd, headerDTO, Set.of(std));
// Then
LN0 ln0 = expectedSCD.streamIEDAdapters()
.findFirst()
.map(iedAdapter -> iedAdapter.getLDeviceAdapterByLdInst("lDeviceInst1").orElseThrow())
.map(LDeviceAdapter::getLN0Adapter)
.map(SclElementAdapter::getCurrentElem)
.orElseThrow(() -> new RuntimeException("Test shouldn't fail here, please check your XML input file"));

assertThat(ln0.getDataSet()).isEmpty();
assertThat(ln0.getInputs().getExtRef()).hasSize(2);
assertFalse(ln0.getInputs().getExtRef().get(0).isSetSrcLDInst());
assertIsMarshallable(expectedSCD.getCurrentElem());
}

@Test
void class_should_not_be_instantiable() {
// Given
Constructor<?>[] constructors = SclAutomationService.class.getDeclaredConstructors();
assertThat(constructors).hasSize(1);
Constructor<?> constructor = constructors[0];
constructor.setAccessible(true);
// When & Then
assertThatThrownBy(constructor::newInstance)
.isInstanceOf(InvocationTargetException.class)
.getCause().isInstanceOf(UnsupportedOperationException.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.lfenergy.compas.scl2007b4.model.TExtRef;
import org.lfenergy.compas.scl2007b4.model.TLLN0Enum;
import org.lfenergy.compas.scl2007b4.model.TServiceType;
import org.lfenergy.compas.scl2007b4.model.*;
import org.lfenergy.compas.sct.commons.exception.ScdException;
import org.lfenergy.compas.sct.commons.scl.dtt.DATypeAdapter;
import org.lfenergy.compas.sct.commons.scl.dtt.DOTypeAdapter;
import org.lfenergy.compas.sct.commons.scl.dtt.DataTypeTemplateAdapter;

import java.util.Comparator;
import java.util.Objects;
Expand Down Expand Up @@ -181,4 +183,29 @@ public String toString() {
'}';

}

/**
* updates bindingInfo from given data
* @param signalInfo contains DAType info to set
* @param doTypeInfo contains DOType info leading to DA
* @throws ScdException thrown when inconsistency between DOType and DAType
*/
public void updateDAInfos(ExtRefSignalInfo signalInfo, DataTypeTemplateAdapter.DOTypeInfo doTypeInfo) throws ScdException {
DaTypeName daTypeName = new DaTypeName(signalInfo.getPDA());
String extDaName = daTypeName.getName();
DOTypeAdapter lastDoTypeAdapter = doTypeInfo.getDoTypeAdapter();
TDA da = lastDoTypeAdapter.getDAByName(extDaName).orElseThrow(() ->
new ScdException(String.format("%s: Unknown DA (%s) in DOType (%s) ", doTypeInfo.getDoTypeName(), extDaName, doTypeInfo.getDoTypeId())));
if (da.getBType() != TPredefinedBasicTypeEnum.STRUCT && !daTypeName.getStructNames().isEmpty()
|| da.getBType() == TPredefinedBasicTypeEnum.STRUCT && daTypeName.getStructNames().isEmpty()) {
throw new ScdException(String.format("Invalid ExtRef signal: no coherence between pDO(%s) and pDA(%s)",
signalInfo.getPDO(), signalInfo.getPDA()));
}
String daTypeId = da.getType();
DATypeAdapter daTypeAdapter = lastDoTypeAdapter.getParentAdapter().getDATypeAdapterById(daTypeId).orElseThrow(() ->
new IllegalArgumentException(String.format("%s: Unknown DA (%s), or no reference to its type", daTypeName, extDaName)));
daTypeAdapter.check(daTypeName);
daTypeName.setFc(da.getFc());
this.daName = daTypeName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,7 @@ public static List<ExtRefBindingInfo> getExtRefBinders(SCL scd, String iedName,
.build();

// check for signal existence
// The below throws exception if the signal doesn't exist
//TODO: create method which purpose is only ckecking instead of this one
abstractLNAdapter.getExtRefsBySignalInfo(signalInfo);
abstractLNAdapter.isExtRefExist(signalInfo);

// find potential binders for the signalInfo
return sclRootAdapter.streamIEDAdapters()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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

/**
* A representation of the model object
Expand Down Expand Up @@ -195,13 +196,7 @@ protected String elementXPath() {
* @return <em>Boolean</em> value of check result
*/
public boolean containsDAWithDAName(String da){
return currentElem.getSDOOrDA()
.stream()
.filter(unNaming -> unNaming.getClass().equals(TDA.class))
.map(TDA.class::cast)
.anyMatch(
tda -> tda.getName().equals(da)
);
return getTdaStream().anyMatch(tda -> tda.getName().equals(da));
}

/**
Expand All @@ -210,10 +205,7 @@ public boolean containsDAWithDAName(String da){
* @return <em>Boolean</em> value of check result
*/
public boolean containsDAWithEnumTypeId(String enumTypeId) {
return currentElem.getSDOOrDA()
.stream()
.filter(unNaming -> unNaming.getClass().equals(TDA.class))
.map(TDA.class::cast)
return getTdaStream()
.anyMatch(
tda -> tda.getBType().equals(TPredefinedBasicTypeEnum.ENUM) &&
tda.getType().equals(enumTypeId)
Expand All @@ -227,7 +219,7 @@ public boolean containsDAWithEnumTypeId(String enumTypeId) {
* @throws ScdException when inconsistency are found in th SCL's
* DataTypeTemplate (unknown reference for example). Which should normally not happens.
*/
Pair<String,DOTypeAdapter> findPathDoType2DA(String daName) throws ScdException {
public Pair<String,DOTypeAdapter> findPathDoTypeToDA(String daName) throws ScdException {
if(containsDAWithDAName(daName)){
// Attention : Do this check before calling this function
// It is not interesting to no have the DO/SDO that references this DoType
Expand Down Expand Up @@ -266,7 +258,7 @@ Pair<String,DOTypeAdapter> findPathDoType2DA(String daName) throws ScdException
* @throws ScdException when inconsistency are found in th SCL's
* DataTypeTemplate (unknown reference for example). Which should normally not happens.
*/
Pair<String,DOTypeAdapter> findPathSDO2DA(String sdoName, String daName) throws ScdException {
Pair<String,DOTypeAdapter> findPathSDOToDA(String sdoName, String daName) throws ScdException {
String errMsg = String.format("No coherence or path between DO/SDO(%s) and DA(%s)", sdoName,daName);
Optional<TSDO> opSdo = getSDOByName(sdoName);
if(opSdo.isEmpty()) {
Expand All @@ -280,7 +272,7 @@ Pair<String,DOTypeAdapter> findPathSDO2DA(String sdoName, String daName) throws
if(doTypeAdapter.containsDAWithDAName(daName)){
return Pair.of(opSdo.get().getName(),doTypeAdapter);
}
return doTypeAdapter.findPathDoType2DA(daName);
return doTypeAdapter.findPathDoTypeToDA(daName);
}

/**
Expand All @@ -289,10 +281,7 @@ Pair<String,DOTypeAdapter> findPathSDO2DA(String sdoName, String daName) throws
* @return <em>Boolean</em> value of check result
*/
public boolean containsDAStructWithDATypeId(String daTypeId) {
return currentElem.getSDOOrDA()
.stream()
.filter(unNaming -> unNaming.getClass().equals(TDA.class))
.map(TDA.class::cast)
return getTdaStream()
.anyMatch(
tda -> TPredefinedBasicTypeEnum.STRUCT.equals(tda.getBType()) &&
tda.getType().equals(daTypeId)
Expand Down Expand Up @@ -422,12 +411,30 @@ public Optional<TSDO> getSDOByName(String sdoName) {
* @return optional of <em>TDA</em> object or empty if unknown DA name
*/
public Optional<TDA> getDAByName(String name) {
for(TUnNaming tUnNaming : currentElem.getSDOOrDA()){
if(tUnNaming.getClass() == TDA.class && ((TDA)tUnNaming).getName().equals(name)){
return Optional.of((TDA)tUnNaming);
}
TDOType tdoType = currentElem;
if (!containsDAWithDAName(name)) {
tdoType = findPathDoTypeToDA(name)
.getValue()
.getCurrentElem();
}
return Optional.empty();
return tdoType.getSDOOrDA()
.stream()
.filter(unNaming -> unNaming.getClass().equals(TDA.class)
&& ((TDA)unNaming).getName().equals(name))
.map(TDA.class::cast)
.findFirst();
}

/**
* Retrieves all TDA in DOType
* @return stream of TDA
*/
private Stream<TDA> getTdaStream() {
return getCurrentElem()
.getSDOOrDA()
.stream()
.filter(unNaming -> unNaming.getClass().equals(TDA.class))
.map(TDA.class::cast);
}

/**
Expand Down
Loading

0 comments on commit 88291aa

Please sign in to comment.