Skip to content

Commit 03ebf01

Browse files
author
Dennis Labordus
committed
First working version of initializing DO Structure.
Signed-off-by: Dennis Labordus <[email protected]>
1 parent fe43f9b commit 03ebf01

File tree

18 files changed

+1316
-117
lines changed

18 files changed

+1316
-117
lines changed

src/editors/ied/da-container.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export class DAContainer extends Container {
118118
// Next create all missing elements (DOI/SDI/DOI)
119119
const newElement = initializeElements(uninitializedTemplateStructure);
120120

121-
if (parentElement && newElement) {
121+
if (newElement) {
122122
const wizard = createDAIWizard(parentElement, newElement, this.element);
123123
if (wizard) this.dispatchEvent(newWizardEvent(wizard));
124124
}

src/editors/protocol104/doi-container.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,14 @@ export class Doi104Container extends LitElement {
6262
daiElement.querySelectorAll(
6363
`Private[type="${PROTOCOL_104_PRIVATE}"] > Address`
6464
)
65-
).sort((addr1, addr2) =>
66-
(addr1.getAttribute('ioa') ?? '').localeCompare(
67-
addr2.getAttribute('ioa') ?? ''
68-
)
65+
).sort(
66+
(addr1, addr2) =>
67+
(addr1.getAttribute('casdu') ?? '').localeCompare(
68+
addr2.getAttribute('casdu') ?? ''
69+
) &&
70+
(addr1.getAttribute('ioa') ?? '').localeCompare(
71+
addr2.getAttribute('ioa') ?? ''
72+
)
6973
);
7074
}
7175

@@ -77,8 +81,12 @@ export class Doi104Container extends LitElement {
7781
daiElement: Element,
7882
addressElement: Element
7983
): void {
84+
const doiElement = daiElement.closest('DOI')!;
85+
const iedElement = doiElement.closest('IED')!;
8086
this.dispatchEvent(
81-
newWizardEvent(editAddressWizard(daiElement, addressElement))
87+
newWizardEvent(
88+
editAddressWizard(iedElement, doiElement, daiElement, addressElement)
89+
)
8290
);
8391
}
8492

src/editors/protocol104/foundation/actions.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { TiInformation } from './cdc.js';
1616
*/
1717
export function createActions(
1818
lnElement: Element,
19+
lnClonedElement: Element,
1920
doElement: Element,
2021
wizard: Element,
2122
ti: string,
@@ -24,6 +25,7 @@ export function createActions(
2425
): Create[] {
2526
return tiInformation.create(
2627
lnElement,
28+
lnClonedElement,
2729
doElement,
2830
wizard,
2931
ti,
@@ -47,6 +49,7 @@ export function createActions(
4749
*/
4850
export function createCheckActions(
4951
lnElement: Element,
52+
lnClonedElement: Element,
5053
doElement: Element,
5154
wizard: Element,
5255
ti: string,
@@ -55,6 +58,7 @@ export function createCheckActions(
5558
if (tiInformation.checkDaPaths && tiInformation.checkCreate) {
5659
return tiInformation.checkCreate(
5760
lnElement,
61+
lnClonedElement,
5862
doElement,
5963
wizard,
6064
ti,

src/editors/protocol104/foundation/cdc.ts

Lines changed: 167 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {
22
Create,
33
getNameAttribute,
4+
getTypeAttribute,
5+
newLogEvent,
46
newWizardEvent,
57
} from '../../../foundation.js';
68

@@ -10,8 +12,18 @@ import {
1012
createPrivateElement,
1113
getPrivateElement,
1214
} 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';
1527

1628
/**
1729
* List of supported Common Data Classes in the 104 protocol.
@@ -41,6 +53,7 @@ export type SupportedCdcType = typeof supportedCdcTypes[number];
4153

4254
export type CreateFunction = (
4355
lnElement: Element,
56+
lnClonedElement: Element,
4457
doElement: Element,
4558
wizard: Element,
4659
ti: string,
@@ -49,6 +62,7 @@ export type CreateFunction = (
4962
) => Create[];
5063
export type CreateCheckFunction = (
5164
lnElement: Element,
65+
lnClonedElement: Element,
5266
doElement: Element,
5367
wizard: Element,
5468
ti: string,
@@ -352,6 +366,7 @@ export const cdcProcessings: Record<
352366
*/
353367
function createAddressAction(
354368
lnElement: Element,
369+
lnClonedElement: Element,
355370
doElement: Element,
356371
wizard: Element,
357372
ti: string,
@@ -360,7 +375,17 @@ function createAddressAction(
360375
): Create[] {
361376
const actions: Create[] = [];
362377

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+
364389
if (daiElements.length > 0) {
365390
addPrefixAndNamespaceToDocument(lnElement.ownerDocument);
366391

@@ -374,7 +399,7 @@ function createAddressAction(
374399
});
375400
}
376401

377-
startEditWizards(wizard, actions);
402+
startEditWizards(wizard, lnElement, lnClonedElement, doElement, actions);
378403
return actions;
379404
}
380405

@@ -392,14 +417,25 @@ function createAddressAction(
392417
*/
393418
function createAddressWithExpectValueAction(
394419
lnElement: Element,
420+
lnClonedElement: Element,
395421
doElement: Element,
396422
wizard: Element,
397423
ti: string,
398424
daPaths: DaSelector[],
399425
inverted: boolean
400426
): Create[] {
401427
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+
}
403439
if (daiElements.length > 0) {
404440
addPrefixAndNamespaceToDocument(lnElement.ownerDocument);
405441

@@ -426,7 +462,7 @@ function createAddressWithExpectValueAction(
426462
});
427463
}
428464

429-
startEditWizards(wizard, actions);
465+
startEditWizards(wizard, lnElement, lnClonedElement, doElement, actions);
430466
return actions;
431467
}
432468

@@ -443,13 +479,24 @@ function createAddressWithExpectValueAction(
443479
*/
444480
function createCheckAddressAction(
445481
lnElement: Element,
482+
lnClonedElement: Element,
446483
doElement: Element,
447484
wizard: Element,
448485
ti: string,
449486
daPaths: DaSelector[]
450487
): Create[] {
451488
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+
}
453500
if (daiElements.length > 0) {
454501
addPrefixAndNamespaceToDocument(lnElement.ownerDocument);
455502

@@ -475,7 +522,7 @@ function createCheckAddressAction(
475522
});
476523
}
477524

478-
startEditWizards(wizard, actions);
525+
startEditWizards(wizard, lnElement, lnClonedElement, doElement, actions);
479526
return actions;
480527
}
481528

@@ -533,7 +580,13 @@ export function createAddressElements(
533580
return addressElements;
534581
}
535582

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 {
537590
actions.forEach(createAction => {
538591
const newElement = <Element>createAction.new.element;
539592
let addressElements: Element[];
@@ -544,29 +597,123 @@ function startEditWizards(wizard: Element, actions: Create[]): void {
544597
}
545598
const parentElement = <Element>createAction.new.parent;
546599
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+
}
552619
});
553620
}
554621

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+
555659
function findOrCreateDaiElements(
556660
lnElement: Element,
661+
lnClonedElement: Element,
557662
doElement: Element,
663+
wizard: Element,
558664
daPaths: DaSelector[]
559-
): Element[] {
665+
): [Create[], Element[]] {
560666
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);
565672
if (foundDaiElements.length > 0) {
566673
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+
}
567714
}
568715
});
569-
return daiElements;
716+
return [actions, daiElements];
570717
}
571718

572719
function createDaiFilter(doElement: Element, daPath: DaSelector): string {
@@ -581,17 +728,6 @@ function createDaiFilter(doElement: Element, daPath: DaSelector): string {
581728
});
582729
return filter;
583730
}
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-
// );
595731

596732
/**
597733
* Indicates if the combination cdc/ti should handle/process the attribute "unitMultiplier" of the Address Element.

0 commit comments

Comments
 (0)