1
1
import {
2
2
Create ,
3
3
getNameAttribute ,
4
+ getTypeAttribute ,
5
+ newLogEvent ,
4
6
newWizardEvent ,
5
7
} from '../../../foundation.js' ;
6
8
@@ -10,8 +12,18 @@ import {
10
12
createPrivateElement ,
11
13
getPrivateElement ,
12
14
} from './private.js' ;
13
- import { getEnumOrds , isEnumDataAttribute } from './foundation.js' ;
14
- import { editAddressWizard } from '../wizards/address' ;
15
+ import {
16
+ findElementInOriginalLNStructure ,
17
+ getCdcValueFromDOElement ,
18
+ getEnumOrds ,
19
+ isEnumDataAttribute ,
20
+ } from './foundation.js' ;
21
+ import { editAddressWizard } from '../wizards/address.js' ;
22
+ import {
23
+ determineUninitializedStructure ,
24
+ initializeElements ,
25
+ } from '../../../foundation/dai.js' ;
26
+ import { get } from 'lit-translate' ;
15
27
16
28
/**
17
29
* List of supported Common Data Classes in the 104 protocol.
@@ -41,6 +53,7 @@ export type SupportedCdcType = typeof supportedCdcTypes[number];
41
53
42
54
export type CreateFunction = (
43
55
lnElement : Element ,
56
+ lnClonedElement : Element ,
44
57
doElement : Element ,
45
58
wizard : Element ,
46
59
ti : string ,
@@ -49,6 +62,7 @@ export type CreateFunction = (
49
62
) => Create [ ] ;
50
63
export type CreateCheckFunction = (
51
64
lnElement : Element ,
65
+ lnClonedElement : Element ,
52
66
doElement : Element ,
53
67
wizard : Element ,
54
68
ti : string ,
@@ -352,6 +366,7 @@ export const cdcProcessings: Record<
352
366
*/
353
367
function createAddressAction (
354
368
lnElement : Element ,
369
+ lnClonedElement : Element ,
355
370
doElement : Element ,
356
371
wizard : Element ,
357
372
ti : string ,
@@ -360,7 +375,17 @@ function createAddressAction(
360
375
) : Create [ ] {
361
376
const actions : Create [ ] = [ ] ;
362
377
363
- const daiElements = findOrCreateDaiElements ( lnElement , doElement , daPaths ) ;
378
+ const [ initializeActions , daiElements ] = findOrCreateDaiElements (
379
+ lnElement ,
380
+ lnClonedElement ,
381
+ doElement ,
382
+ wizard ,
383
+ daPaths
384
+ ) ;
385
+ if ( initializeActions . length > 0 ) {
386
+ actions . push ( ...initializeActions ) ;
387
+ }
388
+
364
389
if ( daiElements . length > 0 ) {
365
390
addPrefixAndNamespaceToDocument ( lnElement . ownerDocument ) ;
366
391
@@ -374,7 +399,7 @@ function createAddressAction(
374
399
} ) ;
375
400
}
376
401
377
- startEditWizards ( wizard , actions ) ;
402
+ startEditWizards ( wizard , lnElement , lnClonedElement , doElement , actions ) ;
378
403
return actions ;
379
404
}
380
405
@@ -392,14 +417,25 @@ function createAddressAction(
392
417
*/
393
418
function createAddressWithExpectValueAction (
394
419
lnElement : Element ,
420
+ lnClonedElement : Element ,
395
421
doElement : Element ,
396
422
wizard : Element ,
397
423
ti : string ,
398
424
daPaths : DaSelector [ ] ,
399
425
inverted : boolean
400
426
) : Create [ ] {
401
427
const actions : Create [ ] = [ ] ;
402
- const daiElements = findOrCreateDaiElements ( lnElement , doElement , daPaths ) ;
428
+
429
+ const [ initializeActions , daiElements ] = findOrCreateDaiElements (
430
+ lnElement ,
431
+ lnClonedElement ,
432
+ doElement ,
433
+ wizard ,
434
+ daPaths
435
+ ) ;
436
+ if ( initializeActions . length > 0 ) {
437
+ actions . push ( ...initializeActions ) ;
438
+ }
403
439
if ( daiElements . length > 0 ) {
404
440
addPrefixAndNamespaceToDocument ( lnElement . ownerDocument ) ;
405
441
@@ -426,7 +462,7 @@ function createAddressWithExpectValueAction(
426
462
} ) ;
427
463
}
428
464
429
- startEditWizards ( wizard , actions ) ;
465
+ startEditWizards ( wizard , lnElement , lnClonedElement , doElement , actions ) ;
430
466
return actions ;
431
467
}
432
468
@@ -443,13 +479,24 @@ function createAddressWithExpectValueAction(
443
479
*/
444
480
function createCheckAddressAction (
445
481
lnElement : Element ,
482
+ lnClonedElement : Element ,
446
483
doElement : Element ,
447
484
wizard : Element ,
448
485
ti : string ,
449
486
daPaths : DaSelector [ ]
450
487
) : Create [ ] {
451
488
const actions : Create [ ] = [ ] ;
452
- const daiElements = findOrCreateDaiElements ( lnElement , doElement , daPaths ) ;
489
+
490
+ const [ initializeActions , daiElements ] = findOrCreateDaiElements (
491
+ lnElement ,
492
+ lnClonedElement ,
493
+ doElement ,
494
+ wizard ,
495
+ daPaths
496
+ ) ;
497
+ if ( initializeActions . length > 0 ) {
498
+ actions . push ( ...initializeActions ) ;
499
+ }
453
500
if ( daiElements . length > 0 ) {
454
501
addPrefixAndNamespaceToDocument ( lnElement . ownerDocument ) ;
455
502
@@ -475,7 +522,7 @@ function createCheckAddressAction(
475
522
} ) ;
476
523
}
477
524
478
- startEditWizards ( wizard , actions ) ;
525
+ startEditWizards ( wizard , lnElement , lnClonedElement , doElement , actions ) ;
479
526
return actions ;
480
527
}
481
528
@@ -533,7 +580,13 @@ export function createAddressElements(
533
580
return addressElements ;
534
581
}
535
582
536
- function startEditWizards ( wizard : Element , actions : Create [ ] ) : void {
583
+ function startEditWizards (
584
+ wizard : Element ,
585
+ lnElement : Element ,
586
+ lnClonedElement : Element ,
587
+ doElement : Element ,
588
+ actions : Create [ ]
589
+ ) : void {
537
590
actions . forEach ( createAction => {
538
591
const newElement = < Element > createAction . new . element ;
539
592
let addressElements : Element [ ] ;
@@ -544,29 +597,123 @@ function startEditWizards(wizard: Element, actions: Create[]): void {
544
597
}
545
598
const parentElement = < Element > createAction . new . parent ;
546
599
const daiElement = parentElement . closest ( 'DAI' ) ;
547
- addressElements . forEach ( addressElement => {
548
- wizard . dispatchEvent (
549
- newWizardEvent ( ( ) => editAddressWizard ( daiElement ! , addressElement ) )
550
- ) ;
551
- } ) ;
600
+ if ( daiElement ) {
601
+ const iedElement = lnElement . closest ( 'IED' ) ! ;
602
+ const doiElement = lnClonedElement . querySelector (
603
+ `:scope > DOI[name="${ getNameAttribute ( doElement ) } "]`
604
+ ) ! ;
605
+
606
+ addressElements . forEach ( addressElement => {
607
+ wizard . dispatchEvent (
608
+ newWizardEvent ( ( ) =>
609
+ editAddressWizard (
610
+ iedElement ,
611
+ doiElement ,
612
+ daiElement ,
613
+ addressElement
614
+ )
615
+ )
616
+ ) ;
617
+ } ) ;
618
+ }
552
619
} ) ;
553
620
}
554
621
622
+ function createTemplateStructure (
623
+ doElement : Element ,
624
+ daPath : DaSelector
625
+ ) : Element [ ] | null {
626
+ let templateStructure : Element [ ] | null = [ doElement ] ;
627
+
628
+ const doc = doElement . ownerDocument ;
629
+ const doType = doElement . getAttribute ( 'type' ) ?? '' ;
630
+ let typeElement = doc . querySelector ( `DOType[id="${ doType } "]` ) ;
631
+
632
+ daPath . path . forEach ( name => {
633
+ // There should be a DOType or DAType set for the current element in the list.
634
+ if ( ! typeElement ) {
635
+ templateStructure = null ;
636
+ return ;
637
+ }
638
+ const daElement = typeElement . querySelector (
639
+ `:scope > DA[name="${ name } "], :scope > BDA[name="${ name } "]`
640
+ ) ;
641
+ // If there is no DA/BDA Element found the structure is incorrect, so just stop.
642
+ if ( daElement === null ) {
643
+ templateStructure = null ;
644
+ return ;
645
+ }
646
+ templateStructure ! . push ( daElement ) ;
647
+
648
+ const bType = daElement . getAttribute ( 'bType' ) ?? '' ;
649
+ if ( bType === 'Struct' ) {
650
+ const type = daElement . getAttribute ( 'type' ) ?? '' ;
651
+ typeElement = doc . querySelector ( `DAType[id="${ type } "]` ) ;
652
+ } else {
653
+ typeElement = null ;
654
+ }
655
+ } ) ;
656
+ return templateStructure ;
657
+ }
658
+
555
659
function findOrCreateDaiElements (
556
660
lnElement : Element ,
661
+ lnClonedElement : Element ,
557
662
doElement : Element ,
663
+ wizard : Element ,
558
664
daPaths : DaSelector [ ]
559
- ) : Element [ ] {
665
+ ) : [ Create [ ] , Element [ ] ] {
560
666
const daiElements : Element [ ] = [ ] ;
561
- const filters =
562
- daPaths . map ( daPath => createDaiFilter ( doElement , daPath ) ) ?? [ ] ;
563
- filters . forEach ( filter => {
564
- const foundDaiElements = lnElement . querySelectorAll ( filter ) ;
667
+ const actions : Create [ ] = [ ] ;
668
+
669
+ daPaths . forEach ( daPath => {
670
+ const filter = createDaiFilter ( doElement , daPath ) ;
671
+ const foundDaiElements = lnClonedElement . querySelectorAll ( filter ) ;
565
672
if ( foundDaiElements . length > 0 ) {
566
673
daiElements . push ( ...Array . from ( foundDaiElements ) ) ;
674
+ } else {
675
+ const templateStructure = createTemplateStructure ( doElement , daPath ) ;
676
+ if ( templateStructure ) {
677
+ const [ parentClonedElement , uninitializedTemplateStructure ] =
678
+ determineUninitializedStructure ( lnClonedElement , templateStructure ) ;
679
+ // Next create all missing elements (DOI/SDI/DOI)
680
+ const newElement = initializeElements ( uninitializedTemplateStructure ) ;
681
+
682
+ // Always add it to the cloned LN Structure.
683
+ parentClonedElement . append ( newElement ) ;
684
+
685
+ // If the parent is the LN Element then use the original LN Element in the action.
686
+ const parentElement = findElementInOriginalLNStructure (
687
+ lnElement ,
688
+ parentClonedElement
689
+ ) ;
690
+ if ( parentElement ) {
691
+ actions . push ( { new : { parent : parentElement , element : newElement } } ) ;
692
+ }
693
+
694
+ if ( newElement . tagName === 'DAI' ) {
695
+ daiElements . push ( newElement ) ;
696
+ } else {
697
+ const daiElement = newElement . querySelector ( 'DAI' ) ! ;
698
+ daiElements . push ( daiElement ) ;
699
+ }
700
+ } else {
701
+ const cdc = getCdcValueFromDOElement ( doElement ) ?? '' ;
702
+ const doType = getTypeAttribute ( doElement ) ?? '' ;
703
+ wizard . dispatchEvent (
704
+ newLogEvent ( {
705
+ kind : 'error' ,
706
+ title : get ( 'protocol104.wizard.error.addAddressError' , {
707
+ structure : daPath . path . join ( ' > ' ) ,
708
+ cdc,
709
+ doType,
710
+ } ) ,
711
+ } )
712
+ ) ;
713
+ }
567
714
}
568
715
} ) ;
569
- return daiElements ;
716
+ return [ actions , daiElements ] ;
570
717
}
571
718
572
719
function createDaiFilter ( doElement : Element , daPath : DaSelector ) : string {
@@ -581,17 +728,6 @@ function createDaiFilter(doElement: Element, daPath: DaSelector): string {
581
728
} ) ;
582
729
return filter ;
583
730
}
584
- // wizard.dispatchEvent(
585
- // newLogEvent({
586
- // kind: 'error',
587
- // title: get('protocol104.wizard.error.addAddressError', {
588
- // filter: filters
589
- // .map(filter => filter.replace(':scope >', ''))
590
- // .join(', '),
591
- // cdc,
592
- // }),
593
- // })
594
- // );
595
731
596
732
/**
597
733
* Indicates if the combination cdc/ti should handle/process the attribute "unitMultiplier" of the Address Element.
0 commit comments