99import org .lfenergy .compas .scl2007b4 .model .SCL ;
1010import org .lfenergy .compas .scl2007b4 .model .TCompasICDHeader ;
1111import org .lfenergy .compas .scl2007b4 .model .TIED ;
12+ import org .lfenergy .compas .sct .commons .dto .ControlBlockNetworkSettings ;
13+ import org .lfenergy .compas .sct .commons .dto .ControlBlockNetworkSettings .Settings ;
1214import org .lfenergy .compas .sct .commons .dto .SclReport ;
1315import org .lfenergy .compas .sct .commons .dto .SclReportItem ;
1416import org .lfenergy .compas .sct .commons .exception .ScdException ;
17+ import org .lfenergy .compas .sct .commons .scl .ied .ControlBlockAdapter ;
1518import org .lfenergy .compas .sct .commons .scl .ied .IEDAdapter ;
1619import org .lfenergy .compas .sct .commons .scl .ied .LDeviceAdapter ;
1720import org .lfenergy .compas .sct .commons .scl .ied .LN0Adapter ;
21+ import org .lfenergy .compas .sct .commons .util .ControlBlockEnum ;
1822import org .lfenergy .compas .sct .commons .util .PrivateEnum ;
23+ import org .lfenergy .compas .sct .commons .util .Utils ;
1924
2025import java .util .*;
2126import java .util .function .Function ;
2227import java .util .stream .Collectors ;
2328import java .util .stream .Stream ;
2429
30+ import static org .lfenergy .compas .sct .commons .dto .ControlBlockNetworkSettings .NetworkRanges ;
31+ import static org .lfenergy .compas .sct .commons .dto .ControlBlockNetworkSettings .RangesPerCbType ;
32+
2533@ UtilityClass
2634public class ExtRefService {
2735
2836 private static final String MESSAGE_MISSING_IED_NAME_PARAMETER = "IED.name parameter is missing" ;
29- private static final String CLIENT_IED_NAME = "The Client IED " ;
3037
3138 /**
3239 * Updates iedName attribute of all ExtRefs in the Scd.
@@ -40,21 +47,21 @@ public static SclReport updateAllExtRefIedNames(SCL scd) {
4047 return new SclReport (sclRootAdapter , iedErrors );
4148 }
4249 Map <String , IEDAdapter > icdSystemVersionToIed = sclRootAdapter .streamIEDAdapters ()
43- .collect (Collectors .toMap (
44- iedAdapter -> PrivateService . extractCompasPrivate ( iedAdapter .getCurrentElem (), TCompasICDHeader . class )
45- .map (TCompasICDHeader ::getICDSystemVersionUUID )
46- .orElseThrow (), // Value presence is checked by method validateIed called above
47- Function .identity ()
48- ));
50+ .collect (Collectors .toMap (
51+ iedAdapter -> iedAdapter .getCompasICDHeader ( )
52+ .map (TCompasICDHeader ::getICDSystemVersionUUID )
53+ .orElseThrow (), // Value presence is checked by method validateIed called above
54+ Function .identity ()
55+ ));
4956
5057 List <SclReportItem > extRefErrors = sclRootAdapter .streamIEDAdapters ()
51- .flatMap (IEDAdapter ::streamLDeviceAdapters )
52- .filter (LDeviceAdapter ::hasLN0 )
53- .map (LDeviceAdapter ::getLN0Adapter )
54- .filter (LN0Adapter ::hasInputs )
55- .map (LN0Adapter ::getInputsAdapter )
56- .map (inputsAdapter -> inputsAdapter .updateAllExtRefIedNames (icdSystemVersionToIed ))
57- .flatMap (List ::stream ).toList ();
58+ .flatMap (IEDAdapter ::streamLDeviceAdapters )
59+ .filter (LDeviceAdapter ::hasLN0 )
60+ .map (LDeviceAdapter ::getLN0Adapter )
61+ .filter (LN0Adapter ::hasInputs )
62+ .map (LN0Adapter ::getInputsAdapter )
63+ .map (inputsAdapter -> inputsAdapter .updateAllExtRefIedNames (icdSystemVersionToIed ))
64+ .flatMap (List ::stream ).toList ();
5865
5966 return new SclReport (sclRootAdapter , extRefErrors );
6067 }
@@ -67,53 +74,74 @@ private static List<SclReportItem> validateIed(SclRootAdapter sclRootAdapter) {
6774
6875 private static List <SclReportItem > checkIedCompasIcdHeaderAttributes (SclRootAdapter sclRootAdapter ) {
6976 return sclRootAdapter .streamIEDAdapters ()
70- .map (iedAdapter -> {
71- Optional <TCompasICDHeader > compasPrivate = PrivateService . extractCompasPrivate ( iedAdapter .getCurrentElem (), TCompasICDHeader . class );
72- if (compasPrivate .isEmpty ()) {
73- return iedAdapter .buildFatalReportItem (String .format ("IED has no Private %s element" , PrivateEnum .COMPAS_ICDHEADER .getPrivateType ()));
74- }
75- if (StringUtils .isBlank (compasPrivate .get ().getICDSystemVersionUUID ())
76- || StringUtils .isBlank (compasPrivate .get ().getIEDName ())) {
77- return iedAdapter .buildFatalReportItem (String .format ("IED private %s as no icdSystemVersionUUID or iedName attribute" ,
78- PrivateEnum .COMPAS_ICDHEADER .getPrivateType ()));
79- }
80- return null ;
81- }
82- ).filter (Objects ::nonNull )
83- .toList ();
77+ .map (iedAdapter -> {
78+ Optional <TCompasICDHeader > compasPrivate = iedAdapter .getCompasICDHeader ( );
79+ if (compasPrivate .isEmpty ()) {
80+ return iedAdapter .buildFatalReportItem (String .format ("IED has no Private %s element" , PrivateEnum .COMPAS_ICDHEADER .getPrivateType ()));
81+ }
82+ if (StringUtils .isBlank (compasPrivate .get ().getICDSystemVersionUUID ())
83+ || StringUtils .isBlank (compasPrivate .get ().getIEDName ())) {
84+ return iedAdapter .buildFatalReportItem (String .format ("IED private %s as no icdSystemVersionUUID or iedName attribute" ,
85+ PrivateEnum .COMPAS_ICDHEADER .getPrivateType ()));
86+ }
87+ return null ;
88+ }
89+ ).filter (Objects ::nonNull )
90+ .toList ();
8491 }
8592
8693 private static List <SclReportItem > checkIedUnityOfIcdSystemVersionUuid (SclRootAdapter sclRootAdapter ) {
8794 Map <String , List <TIED >> systemVersionToIedList = sclRootAdapter .getCurrentElem ().getIED ().stream ()
88- .collect (Collectors .groupingBy (ied -> PrivateService .extractCompasPrivate (ied , TCompasICDHeader .class )
89- .map (TCompasICDHeader ::getICDSystemVersionUUID )
90- .orElse ("" )));
95+ .collect (Collectors .groupingBy (ied -> PrivateService .extractCompasPrivate (ied , TCompasICDHeader .class )
96+ .map (TCompasICDHeader ::getICDSystemVersionUUID )
97+ .orElse ("" )));
9198
9299 return systemVersionToIedList .entrySet ().stream ()
93- .filter (entry -> StringUtils .isNotBlank (entry .getKey ()))
94- .filter (entry -> entry .getValue ().size () > 1 )
95- .map (entry -> SclReportItem .fatal (entry .getValue ().stream ()
96- .map (tied -> new IEDAdapter (sclRootAdapter , tied ))
97- .map (IEDAdapter ::getXPath )
98- .collect (Collectors .joining (", " )),
99- "/IED/Private/compas:ICDHeader[@ICDSystemVersionUUID] must be unique" +
100- " but the same ICDSystemVersionUUID was found on several IED." ))
101- .toList ();
100+ .filter (entry -> StringUtils .isNotBlank (entry .getKey ()))
101+ .filter (entry -> entry .getValue ().size () > 1 )
102+ .map (entry -> SclReportItem .fatal (entry .getValue ().stream ()
103+ .map (tied -> new IEDAdapter (sclRootAdapter , tied ))
104+ .map (IEDAdapter ::getXPath )
105+ .collect (Collectors .joining (", " )),
106+ "/IED/Private/compas:ICDHeader[@ICDSystemVersionUUID] must be unique" +
107+ " but the same ICDSystemVersionUUID was found on several IED." ))
108+ .toList ();
102109 }
103110
111+ /**
112+ * Create All DataSet and ControlBlock in the SCL based on the ExtRef
113+ *
114+ * @param scd input SCD object. It could be modified by adding new DataSet and ControlBlocks
115+ * @return a report with all errors encountered
116+ */
104117 public static SclReport createDataSetAndControlBlocks (SCL scd ) {
105118 SclRootAdapter sclRootAdapter = new SclRootAdapter (scd );
106119 Stream <LDeviceAdapter > lDeviceAdapters = sclRootAdapter .streamIEDAdapters ().flatMap (IEDAdapter ::streamLDeviceAdapters );
107120 return createDataSetAndControlBlocks (sclRootAdapter , lDeviceAdapters );
108121 }
109122
123+ /**
124+ * Create All DataSet and ControlBlock for the ExtRef in given IED
125+ *
126+ * @param scd input SCD object. The object will be modified with the new DataSet and ControlBlocks
127+ * @param targetIedName the name of the IED where the ExtRef are
128+ * @return a report with all the errors encountered
129+ */
110130 public static SclReport createDataSetAndControlBlocks (SCL scd , String targetIedName ) {
111131 SclRootAdapter sclRootAdapter = new SclRootAdapter (scd );
112132 IEDAdapter iedAdapter = sclRootAdapter .getIEDAdapterByName (targetIedName );
113133 return createDataSetAndControlBlocks (sclRootAdapter , iedAdapter .streamLDeviceAdapters ());
114134
115135 }
116136
137+ /**
138+ * Create All DataSet and ControlBlock for the ExtRef in this LDevice
139+ *
140+ * @param scd input SCD object. The object will be modified with the new DataSet and ControlBlocks
141+ * @param targetIedName the name of the IED where the ExtRef are
142+ * @param targetLDeviceInst the name of the LDevice where the ExtRef are
143+ * @return a report with all encountered errors
144+ */
117145 public static SclReport createDataSetAndControlBlocks (SCL scd , String targetIedName , String targetLDeviceInst ) {
118146 if (StringUtils .isBlank (targetIedName )) {
119147 throw new ScdException (MESSAGE_MISSING_IED_NAME_PARAMETER );
@@ -126,9 +154,74 @@ public static SclReport createDataSetAndControlBlocks(SCL scd, String targetIedN
126154
127155 private static SclReport createDataSetAndControlBlocks (SclRootAdapter sclRootAdapter , Stream <LDeviceAdapter > lDeviceAdapters ) {
128156 List <SclReportItem > sclReportItems = lDeviceAdapters
129- .map (LDeviceAdapter ::createDataSetAndControlBlocks )
130- .flatMap (List ::stream )
131- .toList ();
157+ .map (LDeviceAdapter ::createDataSetAndControlBlocks )
158+ .flatMap (List ::stream )
159+ .toList ();
132160 return new SclReport (sclRootAdapter , sclReportItems );
133161 }
162+
163+ /**
164+ * Configure the network for all the ControlBlocks.
165+ * Create (or update if already existing) these elements
166+ * - the Communication/SubNetwork/ConnectedAP/GSE element, for the GSEControl blocks
167+ * - the Communication/SubNetwork/ConnectedAP/SMV element, for the SampledValueControl blocks
168+ *
169+ * @param scd input SCD object. The object will be modified with the new DataGSESet and SMV elements
170+ * @param controlBlockNetworkSettings a method tha gives the network configuration information for a given ControlBlock
171+ * @param rangesPerCbType provide NetworkRanges for GSEControl and SampledValueControl. NetworkRanges contains :
172+ * start-end app APPID range (long value), start-end MAC-Addresses (Mac-Addresses values: Ex: "01-0C-CD-01-01-FF")
173+ * @return a report with all the errors encountered
174+ * @see Utils#macAddressToLong(String) for the expected MAC address format
175+ * @see ControlBlockNetworkSettings
176+ * @see ControlBlockNetworkSettings.RangesPerCbType
177+ * @see ControlBlockNetworkSettings.NetworkRanges
178+ */
179+ public static SclReport configureNetworkForAllControlBlocks (SCL scd , ControlBlockNetworkSettings controlBlockNetworkSettings ,
180+ RangesPerCbType rangesPerCbType ) {
181+ List <SclReportItem > sclReportItems = new ArrayList <>();
182+ sclReportItems .addAll (configureNetworkForControlBlocks (scd , controlBlockNetworkSettings , rangesPerCbType .gse (), ControlBlockEnum .GSE ));
183+ sclReportItems .addAll (configureNetworkForControlBlocks (scd , controlBlockNetworkSettings , rangesPerCbType .sampledValue (), ControlBlockEnum .SAMPLED_VALUE ));
184+ return new SclReport (new SclRootAdapter (scd ), sclReportItems );
185+ }
186+
187+ private static List <SclReportItem > configureNetworkForControlBlocks (SCL scd , ControlBlockNetworkSettings controlBlockNetworkSettings ,
188+ NetworkRanges networkRanges , ControlBlockEnum controlBlockEnum ) {
189+ PrimitiveIterator .OfLong appIdIterator = Utils .sequence (networkRanges .appIdStart (), networkRanges .appIdEnd ());
190+ Iterator <String > macAddressIterator = Utils .macAddressSequence (networkRanges .macAddressStart (), networkRanges .macAddressEnd ());
191+
192+ SclRootAdapter sclRootAdapter = new SclRootAdapter (scd );
193+ return sclRootAdapter .streamIEDAdapters ()
194+ .flatMap (iedAdapter ->
195+ iedAdapter .streamLDeviceAdapters ()
196+ .filter (LDeviceAdapter ::hasLN0 )
197+ .map (LDeviceAdapter ::getLN0Adapter )
198+ .flatMap (ln0Adapter -> ln0Adapter .streamControlBlocks (controlBlockEnum ))
199+ .map (controlBlockAdapter -> configureControlBlockNetwork (controlBlockNetworkSettings , appIdIterator , macAddressIterator , controlBlockAdapter )))
200+ .flatMap (Optional ::stream )
201+ .toList ();
202+ }
203+
204+ private static Optional <SclReportItem > configureControlBlockNetwork (ControlBlockNetworkSettings controlBlockNetworkSettings , PrimitiveIterator .OfLong appIdIterator , Iterator <String > macAddressIterator , ControlBlockAdapter controlBlockAdapter ) {
205+ Settings settings = controlBlockNetworkSettings .getNetworkSettings (controlBlockAdapter );
206+
207+ if (settings == null ) {
208+ return Optional .of (controlBlockAdapter .buildFatalReportItem (
209+ "Cannot configure network for this ControlBlock because no settings was provided" ));
210+ }
211+ if (settings .vlanId () == null ) {
212+ return Optional .of (controlBlockAdapter .buildFatalReportItem (
213+ "Cannot configure network for this ControlBlock because no Vlan Id was provided in the settings" ));
214+ }
215+ if (!appIdIterator .hasNext ()) {
216+ return Optional .of (controlBlockAdapter .buildFatalReportItem (
217+ "Cannot configure network for this ControlBlock because range of appId is exhausted" ));
218+ }
219+ if (!macAddressIterator .hasNext ()) {
220+ return Optional .of (controlBlockAdapter .buildFatalReportItem (
221+ "Cannot configure network for this ControlBlock because range of MAC Address is exhausted" ));
222+ }
223+
224+ return controlBlockAdapter .configureNetwork (appIdIterator .nextLong (), macAddressIterator .next (), settings .vlanId (), settings .vlanPriority (),
225+ settings .minTime (), settings .maxTime ());
226+ }
134227}
0 commit comments