@@ -42,12 +42,26 @@ public class InputsAdapter extends SclElementAdapter<LN0Adapter, TInputs> {
4242 "LDevice with same inst attribute in source IED %s" ;
4343 private static final String MESSAGE_SOURCE_LN_NOT_FOUND = "The signal ExtRef lninst, doName or daName does not match any " +
4444 "source in LDevice %s" ;
45- private static final String MESSAGE_SERVICE_TYPE_MISSING_ON_EXTREF = "The signal ExtRef is missing ServiceType attribute" ;
45+ private static final String MESSAGE_SERVICE_TYPE_MISSING = "The signal ExtRef is missing ServiceType attribute" ;
4646 private static final String MESSAGE_INVALID_SERVICE_TYPE = "The signal ExtRef ServiceType attribute is unexpected : %s" ;
47- private static final String MESSAGE_IED_IS_MISSING_PRIVATE_COMPAS_BAY_UUID = "IED is missing Private/compas:Bay@UUID attribute" ;
48- private static final String MESSAGE_REPORT_EXTREF_DESC_MALFORMED = "ExtRef.serviceType=Report but ExtRef.desc attribute is malformed" ;
47+ private static final String MESSAGE_IED_MISSING_COMPAS_BAY_UUID = "IED is missing Private/compas:Bay@UUID attribute" ;
48+ private static final String MESSAGE_EXTREF_DESC_MALFORMED = "ExtRef.serviceType=Report but ExtRef.desc attribute is malformed" ;
49+ private static final String MESSAGE_LDEVICE_STATUS_UNDEFINED = "The LDevice status is undefined" ;
50+ private static final String MESSAGE_LDEVICE_STATUS_NEITHER_ON_NOR_OFF = "The LDevice status is neither \" on\" nor \" off\" " ;
51+ private static final String MESSAGE_EXTREF_IEDNAME_DOES_NOT_MATCH_ANY_SYSTEM_VERSION_UUID = "The signal ExtRef iedName does not match any " +
52+ "IED/Private/compas:ICDHeader@ICDSystemVersionUUID" ;
53+ private static final String MESSAGE_SOURCE_LDEVICE_STATUS_UNDEFINED = "The signal ExtRef source LDevice %s status is undefined" ;
54+ private static final String MESSAGE_SOURCE_LDEVICE_STATUS_NEITHER_ON_NOR_OFF = "The signal ExtRef source LDevice %s status is neither \" on\" nor \" off\" " ;
55+ private static final String MESSAGE_SOURCE_LDEVICE_STATUS_OFF = "The signal ExtRef source LDevice %s status is off" ;
56+ private static final String MESSAGE_SOURCE_IED_NOT_FOUND = "Source IED not found in SCD" ;
57+ private static final String MESSAGE_SOURCE_IED_MISSING_COMPAS_BAY_UUID = "Source IED is missing Private/compas:Bay@UUID attribute" ;
58+ private static final String MESSAGE_UNABLE_TO_CREATE_DATASET_OR_CONTROLBLOCK = "Could not create DataSet or ControlBlock for this ExtRef : " ;
59+ private static final String MESSAGE_POLL_SERVICE_TYPE_NOT_SUPPORTED = "only GOOSE, SMV and REPORT ServiceType are allowed" ;
60+
4961 private static final int EXTREF_DESC_DA_NAME_POSITION = -2 ;
50- private static final String EXTREF_DESC_DELIMITER = "_" ;
62+ private static final String ATTRIBUTE_VALUE_SEPARATOR = "_" ;
63+ private static final String DATASET_NAME_PREFIX = "DS" + ATTRIBUTE_VALUE_SEPARATOR ;
64+ private static final String CONTROLBLOCK_NAME_PREFIX = "CB" + ATTRIBUTE_VALUE_SEPARATOR ;
5165
5266 /**
5367 * Constructor
@@ -82,7 +96,7 @@ protected String elementXPath() {
8296 public List <SclReportItem > updateAllExtRefIedNames (Map <String , IEDAdapter > icdSystemVersionToIed ) {
8397 Optional <String > optionalLDeviceStatus = getLDeviceAdapter ().getLDeviceStatus ();
8498 if (optionalLDeviceStatus .isEmpty ()) {
85- return List .of (getLDeviceAdapter ().buildFatalReportItem ("The LDevice status is undefined" ));
99+ return List .of (getLDeviceAdapter ().buildFatalReportItem (MESSAGE_LDEVICE_STATUS_UNDEFINED ));
86100 }
87101 String lDeviceStatus = optionalLDeviceStatus .get ();
88102 return switch (lDeviceStatus ) {
@@ -99,7 +113,7 @@ yield getExtRefs().stream()
99113 getExtRefs ().forEach (this ::clearBinding );
100114 yield Collections .emptyList ();
101115 }
102- default -> List .of (getLDeviceAdapter ().buildFatalReportItem ("The LDevice status is neither \" on \" nor \" off \" " ));
116+ default -> List .of (getLDeviceAdapter ().buildFatalReportItem (MESSAGE_LDEVICE_STATUS_NEITHER_ON_NOR_OFF ));
103117 };
104118 }
105119
@@ -148,8 +162,7 @@ private List<TExtRef> getExtRefs() {
148162
149163 private Optional <SclReportItem > validateExtRefSource (TExtRef extRef , IEDAdapter sourceIed ) {
150164 if (sourceIed == null ) {
151- return warningReportItem (extRef , "The signal ExtRef iedName does not match any " +
152- "IED/Private/compas:ICDHeader@ICDSystemVersionUUID" );
165+ return warningReportItem (extRef , MESSAGE_EXTREF_IEDNAME_DOES_NOT_MATCH_ANY_SYSTEM_VERSION_UUID );
153166 }
154167 Optional <LDeviceAdapter > optionalSourceLDevice = sourceIed .findLDeviceAdapterByLdInst (extRef .getLdInst ());
155168 if (optionalSourceLDevice .isEmpty ()) {
@@ -161,16 +174,16 @@ private Optional<SclReportItem> validateExtRefSource(TExtRef extRef, IEDAdapter
161174 }
162175 Optional <String > optionalSourceLDeviceStatus = sourceLDevice .getLDeviceStatus ();
163176 if (optionalSourceLDeviceStatus .isEmpty ()) {
164- return fatalReportItem (extRef , String .format ("The signal ExtRef source LDevice %s status is undefined" ,
177+ return fatalReportItem (extRef , String .format (MESSAGE_SOURCE_LDEVICE_STATUS_UNDEFINED ,
165178 sourceLDevice .getXPath ()));
166179 }
167180 return optionalSourceLDeviceStatus .map (sourceLDeviceStatus ->
168181 switch (sourceLDeviceStatus ) {
169- case OFF -> SclReportItem .warning (extRefXPath (extRef .getDesc ()), String .format ("The signal ExtRef source LDevice %s status is off" ,
182+ case OFF -> SclReportItem .warning (extRefXPath (extRef .getDesc ()), String .format (MESSAGE_SOURCE_LDEVICE_STATUS_OFF ,
170183 sourceLDevice .getXPath ()));
171184 case ON -> null ;
172185 default -> SclReportItem .fatal (extRefXPath (extRef .getDesc ()),
173- String .format ("The signal ExtRef source LDevice %s status is neither \" on \" nor \" off \" " ,
186+ String .format (MESSAGE_SOURCE_LDEVICE_STATUS_NEITHER_ON_NOR_OFF ,
174187 sourceLDevice .getXPath ()));
175188 });
176189 }
@@ -249,7 +262,7 @@ public List<SclReportItem> updateAllSourceDataSetsAndControlBlocks() {
249262 List <TCompasFlow > compasFlows = PrivateService .extractCompasPrivates (currentElem , TCompasFlow .class );
250263 String currentBayUuid = getIedAdapter ().getPrivateCompasBay ().map (TCompasBay ::getUUID ).orElse (null );
251264 if (StringUtils .isBlank (currentBayUuid )) {
252- return List .of (getIedAdapter ().buildFatalReportItem (MESSAGE_IED_IS_MISSING_PRIVATE_COMPAS_BAY_UUID ));
265+ return List .of (getIedAdapter ().buildFatalReportItem (MESSAGE_IED_MISSING_COMPAS_BAY_UUID ));
253266 }
254267 return getExtRefs ().stream ()
255268 .filter (this ::areBindingAttributesPresent )
@@ -281,18 +294,18 @@ private boolean areBindingAttributesPresent(TExtRef tExtRef) {
281294
282295 private Optional <SclReportItem > updateSourceDataSetsAndControlBlocks (TExtRef extRef , String targetBayUuid ) {
283296 if (extRef .getServiceType () == null ) {
284- return fatalReportItem (extRef , MESSAGE_SERVICE_TYPE_MISSING_ON_EXTREF );
297+ return fatalReportItem (extRef , MESSAGE_SERVICE_TYPE_MISSING );
285298 }
286299 Optional <IEDAdapter > optionalSrcIedAdapter = getSclRootAdapter ().findIedAdapterByName (extRef .getIedName ());
287300 if (optionalSrcIedAdapter .isEmpty ()) {
288- return fatalReportItem (extRef , "Source IED not found in SCD" );
301+ return fatalReportItem (extRef , MESSAGE_SOURCE_IED_NOT_FOUND );
289302 }
290303 IEDAdapter sourceIed = optionalSrcIedAdapter .get ();
291304 Optional <String > sourceIedBayUuid = sourceIed .getPrivateCompasBay ()
292305 .map (TCompasBay ::getUUID )
293306 .filter (StringUtils ::isNotBlank );
294307 if (sourceIedBayUuid .isEmpty ()) {
295- return fatalReportItem (extRef , "Source IED is missing Private/compas:Bay@UUID attribute" );
308+ return fatalReportItem (extRef , MESSAGE_SOURCE_IED_MISSING_COMPAS_BAY_UUID );
296309 }
297310
298311 boolean isBayInternal = targetBayUuid .equals (sourceIedBayUuid .get ());
@@ -315,43 +328,56 @@ private Optional<SclReportItem> updateSourceDataSetsAndControlBlocks(TExtRef ext
315328 try {
316329 sourceDas .forEach (sourceDa -> {
317330 String datasetSuffix = generateDataSetSuffix (extRef , sourceDa , isBayInternal );
318- createDataSetWithFCDA (extRef , sourceLDevice , sourceDa , datasetSuffix );
319- createControlBlockWithTarget (extRef , sourceLDevice , sourceDa , datasetSuffix );
331+ String dataSetName = DATASET_NAME_PREFIX + datasetSuffix ;
332+ String cbName = CONTROLBLOCK_NAME_PREFIX + datasetSuffix ;
333+ createDataSetWithFCDA (extRef , sourceLDevice , sourceDa , dataSetName );
334+ createControlBlockWithTarget (extRef , sourceLDevice , sourceDa , cbName , dataSetName );
335+ setExtRefSrcAttributes (extRef , cbName );
320336 });
321337 } catch (ScdException e ) {
322338 // ScdException can be thrown if AccessPoint does not have DataSet/ControlBlock creation capability
323339 log .error (e .getMessage (), e );
324- return fatalReportItem (extRef , "Could not create DataSet for this ExtRef : " + e .getMessage ());
340+ return fatalReportItem (extRef , MESSAGE_UNABLE_TO_CREATE_DATASET_OR_CONTROLBLOCK + e .getMessage ());
325341 }
326342 return Optional .empty ();
327343 }
328344
329- private void createDataSetWithFCDA (TExtRef extRef , LDeviceAdapter sourceLDevice , ResumedDataTemplate sourceDa , String datasetSuffix ) {
330- DataSetAdapter dataSetAdapter = sourceLDevice .getLN0Adapter ().createDataSetIfNotExists ("DS_" + datasetSuffix , ControlBlockEnum .from (extRef .getServiceType ()));
345+ private void createDataSetWithFCDA (TExtRef extRef , LDeviceAdapter sourceLDevice , ResumedDataTemplate sourceDa , String dataSetName ) {
346+ DataSetAdapter dataSetAdapter = sourceLDevice .getLN0Adapter ().createDataSetIfNotExists (dataSetName , ControlBlockEnum .from (extRef .getServiceType ()));
331347 String fcdaDaName = extRef .getServiceType () == TServiceType .REPORT ? null : sourceDa .getDaRef ();
332348 String fcdaLnClass = extRef .getLnClass ().stream ().findFirst ().orElse (null );
333349 dataSetAdapter .createFCDAIfNotExists (extRef .getLdInst (), extRef .getPrefix (), fcdaLnClass , extRef .getLnInst (),
334- sourceDa .getDoRef (), fcdaDaName , sourceDa .getFc ());
350+ sourceDa .getDoRef (),
351+ fcdaDaName ,
352+ sourceDa .getFc ());
335353 }
336354
337- private void createControlBlockWithTarget (TExtRef extRef , LDeviceAdapter sourceLDevice , ResumedDataTemplate sourceDa , String datasetSuffix ) {
338- String cbName = "CB_" + datasetSuffix ;
355+ private void createControlBlockWithTarget (TExtRef extRef , LDeviceAdapter sourceLDevice , ResumedDataTemplate sourceDa , String cbName , String datSet ) {
339356 String cbId = generateControlBlockId (cbName , sourceLDevice .getLdName (), getParentAdapter ());
340- ControlBlockAdapter controlBlockAdapter = sourceLDevice .getLN0Adapter ().createControlBlockIfNotExists (cbName , cbId , "DS_" + datasetSuffix , ControlBlockEnum .from (extRef .getServiceType ()));
357+ ControlBlockAdapter controlBlockAdapter = sourceLDevice .getLN0Adapter ().createControlBlockIfNotExists (cbName , cbId , datSet , ControlBlockEnum .from (extRef .getServiceType ()));
341358 if (sourceDa .getFc () != TFCEnum .ST && controlBlockAdapter .getCurrentElem () instanceof TReportControl tReportControl ){
342359 tReportControl .getTrgOps ().setDchg (false );
343360 tReportControl .getTrgOps ().setQchg (false );
344361 }
345362 controlBlockAdapter .addTargetIfNotExists (getLNAdapter ());
346363 }
347364
365+ private void setExtRefSrcAttributes (TExtRef extRef , String cbName ) {
366+ extRef .setSrcCBName (cbName );
367+ extRef .setSrcLDInst (extRef .getLdInst ());
368+ // srcPrefix, srcLNInst and srcLNClass are set to empty because ControlBlock is created in LN0
369+ extRef .setSrcPrefix (null );
370+ extRef .setSrcLNInst (null );
371+ extRef .unsetSrcLNClass ();
372+ }
373+
348374 private static String generateDataSetSuffix (TExtRef extRef , ResumedDataTemplate sourceDa , boolean isBayInternal ) {
349- return extRef .getLdInst () + "_"
375+ return extRef .getLdInst () + ATTRIBUTE_VALUE_SEPARATOR
350376 + switch (extRef .getServiceType ()) {
351377 case GOOSE -> "G" + ((sourceDa .getFc () == TFCEnum .ST ) ? "S" : "M" );
352378 case SMV -> "SV" ;
353379 case REPORT -> (sourceDa .getFc () == TFCEnum .ST ) ? "DQC" : "CYC" ;
354- case POLL -> throw new IllegalArgumentException ("only GOOSE, SMV and REPORT ServiceType are allowed" );
380+ case POLL -> throw new IllegalArgumentException (MESSAGE_POLL_SERVICE_TYPE_NOT_SUPPORTED );
355381 }
356382 + (isBayInternal ? "I" : "E" );
357383 }
@@ -379,9 +405,9 @@ private Optional<SclReportItem> removeFilteredSourceDas(TExtRef extRef, final Se
379405 }
380406
381407 private Optional <SclReportItem > removeFilterSourceDaForReport (TExtRef extRef , Set <ResumedDataTemplate > sourceDas ) {
382- String daName = Utils .extractField (extRef .getDesc (), EXTREF_DESC_DELIMITER , EXTREF_DESC_DA_NAME_POSITION );
408+ String daName = Utils .extractField (extRef .getDesc (), ATTRIBUTE_VALUE_SEPARATOR , EXTREF_DESC_DA_NAME_POSITION );
383409 if (StringUtils .isBlank (daName )) {
384- return fatalReportItem (extRef , MESSAGE_REPORT_EXTREF_DESC_MALFORMED );
410+ return fatalReportItem (extRef , MESSAGE_EXTREF_DESC_MALFORMED );
385411 }
386412 sourceDas .removeIf (resumedDataTemplate -> !resumedDataTemplate .getDaName ().toString ().equals (daName ));
387413 return Optional .empty ();
0 commit comments