From 627a053b7ae52390c65fc940a067b4d258855632 Mon Sep 17 00:00:00 2001 From: Jakob Vogelsang Date: Thu, 19 Oct 2023 23:42:13 +0200 Subject: [PATCH] feat: describe LogControl --- describe/LN.spec.ts | 6 +++ describe/LN.ts | 21 ++++++++++ describe/LogControl.spec.ts | 80 +++++++++++++++++++++++++++++++++++++ describe/LogControl.ts | 52 ++++++++++++++++++++++++ utils.ts | 2 + 5 files changed, 161 insertions(+) create mode 100644 describe/LogControl.spec.ts create mode 100644 describe/LogControl.ts diff --git a/describe/LN.spec.ts b/describe/LN.spec.ts index a7f0f924..7aafb19c 100644 --- a/describe/LN.spec.ts +++ b/describe/LN.spec.ts @@ -35,6 +35,10 @@ const scl = new DOMParser().parseFromString( + + + + @@ -55,6 +59,8 @@ const scl = new DOMParser().parseFromString( + + diff --git a/describe/LN.ts b/describe/LN.ts index 48514ac9..459e7bf6 100644 --- a/describe/LN.ts +++ b/describe/LN.ts @@ -8,6 +8,7 @@ import { LNodeTypeDescription, isLNodeTypeDescription, } from "./LNodeType.js"; +import { LogControlDescription, describeLogControl } from "./LogControl.js"; import { NamingDescription, describeNaming } from "./Naming.js"; import { ReportControlDescription, @@ -17,6 +18,7 @@ import { describeVal, compareBySGroup } from "./Val.js"; export interface LNDescription extends NamingDescription { reports: Record; + logControls: Record; lnType: LNodeTypeDescription; } @@ -68,6 +70,24 @@ function getNextDataType( else return dataType.bdas[path[index]]; } +function logControls(element: Element): Record { + const unsortedLogControls: Record = {}; + + Array.from(element.children) + .filter((child) => child.tagName === "LogControl") + .forEach((logControl) => { + const name = logControl.getAttribute("name"); + const logControlDescription = describeLogControl(logControl); + if (name && !unsortedLogControls[name] && logControlDescription) + unsortedLogControls[name] = logControlDescription; + }); + + return sortRecord(unsortedLogControls) as Record< + string, + LogControlDescription + >; +} + /** Returns leaf data attribute (BDA or DA) from * LNodeTypeDescription containing vals * @param path - parent DOI/SDI/DAI name attributes @@ -138,5 +158,6 @@ export function LN(element: Element): LNDescription | undefined { ...describeNaming(element), lnType, reports: reportControls(element), + logControls: logControls(element), }; } diff --git a/describe/LogControl.spec.ts b/describe/LogControl.spec.ts new file mode 100644 index 00000000..f3c42f27 --- /dev/null +++ b/describe/LogControl.spec.ts @@ -0,0 +1,80 @@ +import { expect } from "chai"; +import { describeLogControl } from "./LogControl.js"; + +const scl = new DOMParser().parseFromString( + ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `, + "application/xml", +); + +const baseLogControl = scl.querySelector(`LogControl[name="baseLogControl"]`)!; +const equalLogControl = scl.querySelector( + 'LogControl[name="equalLogControl"]', +)!; +const diffLogControl = scl.querySelector('LogControl[name="diffLogControl"]')!; +const invalidLogControl = scl.querySelector( + 'LogControl[name="invalidLogControl"]', +)!; +const missingLogName = scl.querySelector('LogControl[name="missingLogName"]')!; + +describe("Description for SCL schema type LogControl", () => { + it("returns undefined with invalid data", () => + expect(describeLogControl(invalidLogControl)).to.be.undefined); + + it("returns undefined with invalid logName attribute", () => + expect(describeLogControl(missingLogName)).to.be.undefined); + + it("returns same description with semantically equal Control's", () => + expect(JSON.stringify(describeLogControl(baseLogControl))).to.equal( + JSON.stringify(describeLogControl(equalLogControl)), + )); + + it("returns different description with unequal Control elements", () => + expect(JSON.stringify(describeLogControl(baseLogControl))).to.not.equal( + JSON.stringify(describeLogControl(diffLogControl)), + )); +}); diff --git a/describe/LogControl.ts b/describe/LogControl.ts new file mode 100644 index 00000000..c7a7fcf2 --- /dev/null +++ b/describe/LogControl.ts @@ -0,0 +1,52 @@ +import { + ControlWithTriggerOptDescription, + describeControlWithTriggerOpt, +} from "./ControlWithTriggerOpt.js"; + +export interface LogControlDescription + extends ControlWithTriggerOptDescription { + /** ReportControl attribute ldInst. */ + ldInst: string | null; + /** LogControl attribute prefix defaulted to "". */ + prefix: string; + /** LogControl attribute lnClass defaulted to "LLN0". */ + lnClass: string; + /** LogControl attribute lnInst. */ + lnInst: string | null; + /** LogControl attribute logName. Must point to valid `Log` element */ + logName: string; + /** LogControl attribute logEna defaulted to true. */ + logEna: boolean; + /** LogControl attribute reasonCode defaulted to true. */ + reasonCode: boolean; + /** LogCOntrol attribute bufTime defaulted to "0". */ + bufTime: number; +} + +export function describeLogControl( + element: Element, +): LogControlDescription | undefined { + const controlWithTriggerOptDesc = describeControlWithTriggerOpt(element); + if (!controlWithTriggerOptDesc) return; + + const logName = element.getAttribute("logName"); + if (!logName) return; + + const logControlDescription: LogControlDescription = { + ...controlWithTriggerOptDesc, + ldInst: element.getAttribute("ldInst"), + prefix: element.getAttribute("prefix") ?? "", + lnClass: element.getAttribute("lnClass") ?? "LLN0", + lnInst: element.getAttribute("lnInst"), + logEna: element.getAttribute("logEna") === "false" ? false : true, + reasonCode: element.getAttribute("reasonCode") === "false" ? false : true, + bufTime: 0, + logName, + }; + + const bufTime = element.getAttribute("bufTime"); + if (bufTime && !isNaN(parseInt(bufTime, 10))) + logControlDescription.bufTime = parseInt(bufTime, 10); + + return logControlDescription; +} diff --git a/utils.ts b/utils.ts index 105cc994..f43e1935 100644 --- a/utils.ts +++ b/utils.ts @@ -1,10 +1,12 @@ import { DADescription } from "./describe/DADescription.js"; import { DODescription } from "./describe/DODescription.js"; +import { LogControlDescription } from "./describe/LogControl.js"; import { ReportControlDescription } from "./describe/ReportControl.js"; import { SDODescription } from "./describe/SDODescription.js"; type SortedObjects = | DADescription + | LogControlDescription | SDODescription | ReportControlDescription | DODescription;