packages/dmn-feel-antlr4-parser/src/parser/IdentifiersRepository.ts (719 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import { DataType } from "./DataType"; import { FeelSyntacticSymbolNature } from "./FeelSyntacticSymbolNature"; import { IdentifierContext } from "./IdentifierContext"; import { DMN15__tBusinessKnowledgeModel, DMN15__tConditional, DMN15__tContext, DMN15__tContextEntry, DMN15__tDecision, DMN15__tDecisionService, DMN15__tDecisionTable, DMN15__tDefinitions, DMN15__tFilter, DMN15__tFor, DMN15__tFunctionDefinition, DMN15__tInformationRequirement, DMN15__tInputClause, DMN15__tInputData, DMN15__tInvocation, DMN15__tItemDefinition, DMN15__tKnowledgeRequirement, DMN15__tList, DMN15__tLiteralExpression, DMN15__tQuantified, DMN15__tRelation, } from "@kie-tools/dmn-marshaller/dist/schemas/dmn-1_5/ts-gen/types"; import { Expression } from "./Expression"; import { DmnLatestModel } from "@kie-tools/dmn-marshaller"; import { BuiltInTypes } from "./BuiltInTypes"; export type ExpressionSource = { text?: { __$$text: string }; "@_id"?: string }; export type DmnLiteralExpression = { __$$element: "literalExpression" } & DMN15__tLiteralExpression; export type DmnInvocation = { __$$element: "invocation" } & DMN15__tInvocation; export type DmnDecisionTable = { __$$element: "decisionTable" } & DMN15__tDecisionTable; export type DmnContext = { __$$element: "context" } & DMN15__tContext; export type DmnFunctionDefinition = { __$$element: "functionDefinition" } & DMN15__tFunctionDefinition; export type DmnRelation = { __$$element: "relation" } & DMN15__tRelation; export type DmnList = { __$$element: "list" } & DMN15__tList; export type DmnConditional = { __$$element: "conditional" } & DMN15__tConditional; export type DmnFilter = { __$$element: "filter" } & DMN15__tFilter; export type DmnFor = { __$$element: "for" } & DMN15__tFor; export type DmnEvery = { __$$element: "every" } & DMN15__tQuantified; export type DmnSome = { __$$element: "some" } & DMN15__tQuantified; export type DmnDecisionNode = { __$$element: "decision" } & DMN15__tDecision; export type DmnDefinitions = DMN15__tDefinitions; export type DmnKnowledgeRequirement = DMN15__tKnowledgeRequirement; export type DmnContextEntry = DMN15__tContextEntry; type DmnBusinessKnowledgeModel = DMN15__tBusinessKnowledgeModel; type DmnItemDefinition = DMN15__tItemDefinition; type DmnInputData = DMN15__tInputData; type DmnInformationRequirement = DMN15__tInformationRequirement; type DmnDecisionService = DMN15__tDecisionService; export class IdentifiersRepository { private readonly _identifiersContextIndexedByUuid: Map<string, IdentifierContext>; private readonly _expressionsIndexedByUuid: Map<string, Expression>; private readonly _dataTypes: Map<string, DataType>; private readonly _dataTypeIndexedByUuid: Map<string, DataType>; private readonly _importedIdentifiers: Map<string, Array<IdentifierContext>>; private readonly _importedDataTypes: Map<string, Array<DataType>>; private currentIdentifierNamePrefix: string; private currentUuidPrefix: string; constructor( private dmnDefinitions: DmnDefinitions, private externalDefinitions?: Map<string, DmnLatestModel> ) { this._dataTypes = new Map([ [BuiltInTypes.Number.name, BuiltInTypes.Number], [BuiltInTypes.Boolean.name, BuiltInTypes.Boolean], [BuiltInTypes.String.name, BuiltInTypes.String], [BuiltInTypes.DaysAndTimeDuration.name, BuiltInTypes.DaysAndTimeDuration], [BuiltInTypes.DateAndTime.name, BuiltInTypes.DateAndTime], [BuiltInTypes.YearsAndMonthsDuration.name, BuiltInTypes.YearsAndMonthsDuration], [BuiltInTypes.Time.name, BuiltInTypes.Time], [BuiltInTypes.Date.name, BuiltInTypes.Date], ]); this._identifiersContextIndexedByUuid = new Map<string, IdentifierContext>(); this._expressionsIndexedByUuid = new Map<string, Expression>(); this._dataTypeIndexedByUuid = new Map<string, DataType>(); this._importedIdentifiers = new Map<string, Array<IdentifierContext>>(); this._importedDataTypes = new Map<string, Array<DataType>>(); this.loadImportedIdentifiers(dmnDefinitions, externalDefinitions); this.currentIdentifierNamePrefix = ""; this.currentUuidPrefix = ""; this.loadIdentifiers(dmnDefinitions); } get identifiersContextIndexedByUuid(): Map<string, IdentifierContext> { return this._identifiersContextIndexedByUuid; } get expressionsIndexedByUuid(): Map<string, Expression> { return this._expressionsIndexedByUuid; } get dataTypeIndexedByUuid(): Map<string, DataType> { return this._dataTypeIndexedByUuid; } get importedDataTypes(): Map<string, Array<DataType>> { return this._importedDataTypes; } get importedIdentifiers(): Map<string, Array<IdentifierContext>> { return this._importedIdentifiers; } get identifiers(): Map<string, IdentifierContext> { return this._identifiersContextIndexedByUuid; } get dataTypes(): Map<string, DataType> { return this._dataTypes; } get expressions(): Map<string, Expression> { return this._expressionsIndexedByUuid; } public reload() { this._identifiersContextIndexedByUuid.clear(); this._expressionsIndexedByUuid.clear(); this._dataTypeIndexedByUuid.clear(); this._importedIdentifiers.clear(); this._importedDataTypes.clear(); this.loadImportedIdentifiers(this.dmnDefinitions, this.externalDefinitions); this.currentIdentifierNamePrefix = ""; this.currentUuidPrefix = ""; this.loadIdentifiers(this.dmnDefinitions); } private createDataTypes(definitions: DmnDefinitions) { definitions.itemDefinition?.forEach((itemDefinition) => { const dataType = this.createDataType(itemDefinition); this._dataTypeIndexedByUuid.set(dataType.uuid, dataType); this.addImportedDataType(dataType); itemDefinition.itemComponent?.forEach((itemComponent) => { const innerType = this.createInnerType(itemComponent); this._dataTypeIndexedByUuid.set(innerType.uuid, innerType); this.addImportedDataType(innerType); dataType.properties.set(innerType.name, innerType); }); this.dataTypes.set(dataType.name, dataType); }); } private addImportedDataType(dataType: DataType) { if (this.currentIdentifierNamePrefix.length != 0) { if (!this._importedDataTypes.has(this.currentIdentifierNamePrefix)) { this._importedDataTypes.set(this.currentIdentifierNamePrefix, []); } this._importedDataTypes.get(this.currentIdentifierNamePrefix)?.push(dataType); } } private loadIdentifiersFromDefinitions(definitions: DmnDefinitions) { definitions.drgElement?.forEach((drg) => { switch (drg.__$$element) { case "decision": this.loadIdentifiersFromDecision(drg); break; case "inputData": this.loadIdentifiersFromInputData(drg); break; case "businessKnowledgeModel": this.loadIdentifiersFromBkm(drg); break; case "decisionService": this.loadIdentifiersFromDecisionService(drg); break; default: // Do nothing because it is an element that does not declare variables break; } }); } private loadIdentifiersFromInputData(drg: DmnInputData) { this.addIdentifierContext({ uuid: drg["@_id"] ?? "", identifierDefinedByTheContext: drg["@_name"], kind: FeelSyntacticSymbolNature.GlobalVariable, parentContext: undefined, typeRef: drg.variable?.["@_typeRef"], applyValueToSource: (value) => { drg["@_name"] = value; }, applyTypeRefToSource: (value) => { if (drg.variable) { if (typeof value === "string") { drg.variable["@_typeRef"] = value; } else { drg.variable["@_typeRef"] = value?.typeRef; } } }, }); } private loadIdentifiersFromDecisionService(drg: DmnDecisionService) { this.addIdentifierContext({ uuid: drg["@_id"] ?? "", identifierDefinedByTheContext: drg["@_name"], kind: FeelSyntacticSymbolNature.Invocable, parentContext: undefined, typeRef: drg.variable?.["@_typeRef"], applyValueToSource: (value) => { drg["@_name"] = value; }, applyTypeRefToSource: (value) => { if (drg.variable) { if (typeof value === "string") { drg.variable["@_typeRef"] = value; } else { drg.variable["@_typeRef"] = value?.typeRef; } } }, }); } private loadIdentifiersFromBkm(drg: DmnBusinessKnowledgeModel) { const parent = this.addIdentifierContext({ uuid: drg["@_id"] ?? "", identifierDefinedByTheContext: drg["@_name"], kind: FeelSyntacticSymbolNature.Invocable, parentContext: undefined, typeRef: drg.variable?.["@_typeRef"], applyValueToSource: (value) => { drg["@_name"] = value; }, applyTypeRefToSource: (value) => { if (drg.variable) { if (typeof value === "string") { drg.variable["@_typeRef"] = value; } else { drg.variable["@_typeRef"] = value?.typeRef; } } }, }); if (drg.encapsulatedLogic) { let parentElement = parent; if (drg.encapsulatedLogic.formalParameter) { for (const parameter of drg.encapsulatedLogic.formalParameter) { parentElement = this.addIdentifierContext({ uuid: parameter["@_id"] ?? "", identifierDefinedByTheContext: parameter["@_name"] ?? "<parameter>", kind: FeelSyntacticSymbolNature.Parameter, parentContext: parentElement, applyValueToSource: (value) => { parameter["@_name"] = value; }, }); } } if (drg.encapsulatedLogic.expression) { this.addInnerExpression(parentElement, drg.encapsulatedLogic.expression); } } } private loadIdentifiersFromDecision(drg: DmnDecisionNode) { const parent: IdentifierContext = this.addIdentifierContext({ uuid: drg["@_id"] ?? "", identifierDefinedByTheContext: drg["@_name"], kind: FeelSyntacticSymbolNature.InvisibleVariables, parentContext: undefined, typeRef: drg.variable?.["@_typeRef"], applyValueToSource: (value) => { drg["@_name"] = value; }, applyTypeRefToSource: (value) => { if (drg.variable) { if (typeof value === "string") { drg.variable["@_typeRef"] = value; } else { drg.variable["@_typeRef"] = value?.typeRef; } } }, }); if (drg.informationRequirement) { for (const requirement of drg.informationRequirement) { this.addInputVariable(parent, requirement); } } if (drg.knowledgeRequirement) { for (const knowledgeRequirement of drg.knowledgeRequirement) { this.addInputVariableFromKnowledge(parent, knowledgeRequirement); } } if (drg.expression) { this.addInnerExpression(parent, drg.expression); } } private addIdentifierContext(args: { uuid: string; identifierDefinedByTheContext: string; kind: FeelSyntacticSymbolNature; parentContext?: IdentifierContext; typeRef?: string; allowDynamicVariables?: boolean; applyValueToSource?: (value: string) => void; applyTypeRefToSource?: (value: DataType | string | undefined) => void; }) { const variableContext = this.createIdentifierContext( this.buildIdentifierUuid(args.uuid), this.buildName(args.identifierDefinedByTheContext), args.kind, args.parentContext, args.typeRef, args.allowDynamicVariables, args.applyValueToSource, args.applyTypeRefToSource ); if (this.currentIdentifierNamePrefix.length != 0) { if (!this._importedIdentifiers.has(this.currentIdentifierNamePrefix)) { this._importedIdentifiers.set(this.currentIdentifierNamePrefix, []); } this._importedIdentifiers.get(this.currentIdentifierNamePrefix)?.push(variableContext); } this._identifiersContextIndexedByUuid.set(this.buildIdentifierUuid(args.uuid), variableContext); return variableContext; } private createIdentifierContext( uuid: string, identifierDefinedByTheContext: string, variableType: FeelSyntacticSymbolNature, parent: IdentifierContext | undefined, typeRef: string | undefined, allowDynamicVariables: boolean | undefined, applyValueToSource?: (value: string) => void, applyTypeRefToSource?: (value: DataType | string | undefined) => void ): IdentifierContext { return { uuid: uuid, children: new Map<string, IdentifierContext>(), parent: parent, inputIdentifiers: new Array<string>(), allowDynamicVariables: allowDynamicVariables, identifier: { value: identifierDefinedByTheContext, feelSyntacticSymbolNature: variableType, typeRef: this.getTypeRef(typeRef), expressionsThatUseTheIdentifier: new Map<string, Expression>(), applyValueToSource() { if (applyValueToSource) { applyValueToSource(this.value); } }, applyTypeRefToSource() { if (applyTypeRefToSource) { applyTypeRefToSource(this.typeRef); } }, }, }; } public getTypeRef(typeRef: string | undefined) { return this.dataTypes.has(typeRef ?? "") ? this.dataTypes.get(typeRef ?? "") : typeRef; } private createDataType(itemDefinition: DmnItemDefinition) { const name = this.buildName(itemDefinition["@_name"]); const dataType: DataType = { uuid: itemDefinition["@_id"] ?? "datatype_uuid", name: name, properties: new Map<string, DataType>(), typeRef: itemDefinition["typeRef"]?.__$$text ?? itemDefinition["@_name"], source: { value: name, feelSyntacticSymbolNature: FeelSyntacticSymbolNature.GlobalVariable, expressionsThatUseTheIdentifier: new Map<string, Expression>(), }, }; return dataType; } private createInnerType(itemComponent: DmnItemDefinition) { const dataType: DataType = { uuid: itemComponent["@_id"] ?? "item_uuid", name: itemComponent["@_name"], properties: this.buildProperties(itemComponent), typeRef: itemComponent["typeRef"]?.__$$text ?? itemComponent["@_name"], source: { value: itemComponent["@_name"], feelSyntacticSymbolNature: FeelSyntacticSymbolNature.GlobalVariable, expressionsThatUseTheIdentifier: new Map<string, Expression>(), }, }; return dataType; } private buildProperties(itemComponent: DmnItemDefinition): Map<string, DataType> { const properties = new Map<string, DataType>(); itemComponent.itemComponent?.forEach((def) => { const property: DataType = { uuid: def["@_id"] ?? "root_property", name: def["@_name"], properties: this.buildProperties(def), typeRef: def["typeRef"]?.__$$text ?? def["@_name"], source: { value: def["@_name"], feelSyntacticSymbolNature: FeelSyntacticSymbolNature.GlobalVariable, expressionsThatUseTheIdentifier: new Map<string, Expression>(), }, }; this._dataTypeIndexedByUuid.set(property.uuid, property); properties.set(property.name, property); }); return properties; } private addExpression(parent: IdentifierContext, element: ExpressionSource) { const id = element["@_id"] ?? ""; const expression = new Expression(id, element); this._expressionsIndexedByUuid.set(id, expression); this.addIdentifierContext({ uuid: id, identifierDefinedByTheContext: "", kind: FeelSyntacticSymbolNature.LocalVariable, parentContext: parent, }); } private addInvocation(parent: IdentifierContext, element: DmnInvocation) { if (element.binding) { for (const bindingElement of element.binding) { if (bindingElement.expression) { this.addInnerExpression(parent, bindingElement.expression); } } } } private addContext(parent: IdentifierContext, element: DmnContext) { let parentNode = parent; if (element.contextEntry) { for (const innerEntry of element.contextEntry) { parentNode = this.addContextEntry(parentNode, innerEntry); } } } private addContextEntry(parentNode: IdentifierContext, contextEntry: DmnContextEntry) { const variableNode = this.addIdentifierContext({ uuid: contextEntry.variable?.["@_id"] ?? "", identifierDefinedByTheContext: contextEntry.variable?.["@_name"] ?? "", kind: FeelSyntacticSymbolNature.LocalVariable, parentContext: parentNode, typeRef: contextEntry.variable?.["@_typeRef"], applyValueToSource: (value) => { if (contextEntry.variable) { contextEntry.variable["@_name"] = value; } }, applyTypeRefToSource: (value) => { if (contextEntry.variable) { if (typeof value === "string") { contextEntry.variable["@_typeRef"] = value; } else { contextEntry.variable["@_typeRef"] = value?.typeRef; } } }, }); parentNode.children.set(variableNode.uuid, variableNode); if (contextEntry.expression) { if (contextEntry.expression.__$$element) { // The parent is always the previous node to prevent recursive calls. // Consider this example: // // [ROOT] Context Expression // [X] Client DTI | [A] // [Y] Some Other | [B] // [Z] And Another | [C] // // Inside the B we can not call "Some Other" for instance, but we can call "Client DTI" // // So the structure for that case should be: // [ROOT] // / \ // [X] [A] // / \ // [Y] [B] // / \ // [Z] [C] // // So in that case, inside "C" we recognize Y, X and ROOT // Inside B, X and ROOT // // By "ROOT" we understand the root expression which for example // can be the Decision Node itself and its input nodes. this.addInnerExpression(parentNode, contextEntry.expression); } } return variableNode; } private addFunctionDefinition(parent: IdentifierContext, element: DmnFunctionDefinition) { let parentElement = parent; if (element.formalParameter) { for (const parameter of element.formalParameter) { parentElement = this.addIdentifierContext({ uuid: parameter["@_id"] ?? "", identifierDefinedByTheContext: parameter["@_name"] ?? "<parameter>", kind: FeelSyntacticSymbolNature.Parameter, parentContext: parentElement, applyValueToSource: (value) => { parameter["@_name"] = value; }, }); } } if (element.expression) { this.addInnerExpression(parentElement, element.expression); } } private addRelation(parent: IdentifierContext, element: DmnRelation) { if (element.row) { for (const rowElement of element.row) { if (rowElement.expression) { for (const expression of rowElement.expression) { this.addInnerExpression(parent, expression); } } } } } private addList(parent: IdentifierContext, element: DmnList) { if (element.expression) { for (const expression of element.expression) { if (expression) { this.addInnerExpression(parent, expression); } } } } private addConditional(parent: IdentifierContext, element: DmnConditional) { if (element.if?.expression) { this.addInnerExpression(parent, element.if.expression); } if (element.then?.expression) { this.addInnerExpression(parent, element.then.expression); } if (element.else?.expression) { this.addInnerExpression(parent, element.else.expression); } } private addIterable(parent: IdentifierContext, expression: DmnSome | DmnEvery) { const localParent = this.addIteratorVariable(parent, expression); if (expression.in.expression) { this.addInnerExpression(localParent, expression.in.expression); } if (expression.satisfies.expression) { this.addInnerExpression(localParent, expression.satisfies.expression); } } private addFor(parent: IdentifierContext, expression: DmnFor) { const localParent = this.addIteratorVariable(parent, expression); if (expression.return.expression) { this.addInnerExpression(localParent, expression.return.expression); } if (expression.in.expression) { this.addInnerExpression(localParent, expression.in.expression); } } private addFilterVariable(parent: IdentifierContext, expression: DmnFilter) { let type = undefined; // We're assuming that the 'in' expression is with the correct type (a list of @_typeRef). // If it is not the expression will fail anyway. if (expression.in.expression) { type = expression.in.expression["@_typeRef"]; } return this.addIdentifierContext({ uuid: expression["@_id"] ?? "", identifierDefinedByTheContext: "item", kind: FeelSyntacticSymbolNature.LocalVariable, parentContext: parent, typeRef: type, allowDynamicVariables: true, }); } private addIteratorVariable(parent: IdentifierContext, expression: DmnFor | DmnEvery | DmnSome) { let localParent = parent; if (expression["@_iteratorVariable"]) { let type = undefined; // We're assuming that the 'in' expression is with the correct type (a list of @_typeRef). // If it is not the expression will fail anyway. if (expression.in.expression) { type = expression.in.expression["@_typeRef"]; } localParent = this.addIdentifierContext({ uuid: expression["@_id"] ?? "", identifierDefinedByTheContext: expression["@_iteratorVariable"], kind: FeelSyntacticSymbolNature.LocalVariable, parentContext: parent, typeRef: type, allowDynamicVariables: true, applyValueToSource: (value) => { expression["@_iteratorVariable"] = value; }, applyTypeRefToSource: (value) => { if (expression.in.expression) { if (typeof value === "string") { expression.in.expression["@_typeRef"] = value; } else { expression.in.expression["@_typeRef"] = value?.typeRef; } } }, }); } return localParent; } private addFilter(parent: IdentifierContext, expression: DmnFilter) { if (expression.in.expression) { this.addInnerExpression(parent, expression.in.expression); } const localParent = this.addFilterVariable(parent, expression); if (expression.match.expression) { this.addInnerExpression(localParent, expression.match.expression); } } private addInnerExpression( parent: IdentifierContext, expression: | DmnLiteralExpression | DmnInvocation | DmnDecisionTable | DmnContext | DmnFunctionDefinition | DmnRelation | DmnList | DmnFor | DmnFilter | DmnEvery | DmnSome | DmnConditional ) { switch (expression.__$$element) { case "literalExpression": this.addExpression(parent, expression); break; case "invocation": this.addInvocation(parent, expression); break; case "decisionTable": // It doesn't define variables, but we need it to create its own context to use variables inside of Decision Table. this.addDecisionTable(parent, expression); break; case "context": this.addContext(parent, expression); break; case "functionDefinition": this.addFunctionDefinition(parent, expression); break; case "relation": this.addRelation(parent, expression); break; case "list": this.addList(parent, expression); break; case "conditional": this.addConditional(parent, expression); break; case "every": case "some": this.addIterable(parent, expression); break; case "for": this.addFor(parent, expression); break; case "filter": this.addFilter(parent, expression); break; default: // throw new Error("Unknown or not supported type for expression."); } } private addDecisionTableEntryNode(parent: IdentifierContext, entryNode: ExpressionSource) { const ruleInputElementNode = this.addIdentifierContext({ uuid: entryNode["@_id"] ?? "", identifierDefinedByTheContext: "", kind: FeelSyntacticSymbolNature.LocalVariable, parentContext: parent, }); parent.children.set(ruleInputElementNode.uuid, ruleInputElementNode); this.addExpression(parent, entryNode); } private addDecisionTableInputEntryNode(parent: IdentifierContext, inputEntryNode: DMN15__tInputClause) { const identifierContext = this.addIdentifierContext({ uuid: inputEntryNode["@_id"] ?? "", identifierDefinedByTheContext: "", kind: FeelSyntacticSymbolNature.LocalVariable, parentContext: parent, }); parent.children.set(identifierContext.uuid, identifierContext); // Notice that the expression of the inputEntryNode it is in an inner element, NOT in the inputEntryNode by itself. this.addExpression(parent, inputEntryNode.inputExpression); } private addDecisionTable(parent: IdentifierContext, decisionTable: DmnDecisionTable) { const addedIdentifierContext = this.addIdentifierContext({ uuid: decisionTable["@_id"] ?? "", identifierDefinedByTheContext: "", kind: FeelSyntacticSymbolNature.LocalVariable, parentContext: parent, }); parent.children.set(addedIdentifierContext.uuid, addedIdentifierContext); // We need to create Identifier Context for each cell of the Decision Table to be able to have // autocomplete and refactor inside of those, otherwise the parser will not find the context to get the identifiers. if (decisionTable.rule) { for (const ruleElement of decisionTable.rule) { ruleElement.inputEntry?.forEach((inputElement) => this.addDecisionTableEntryNode(parent, inputElement)); ruleElement.outputEntry?.forEach((outputElement) => this.addDecisionTableEntryNode(parent, outputElement)); } } // The Decision Table inputs also have expressions and its own contexts. if (decisionTable.input) { for (const inputClause of decisionTable.input) { this.addDecisionTableInputEntryNode(addedIdentifierContext, inputClause); } } this.addIdentifierContext({ uuid: addedIdentifierContext.uuid, identifierDefinedByTheContext: "", kind: FeelSyntacticSymbolNature.LocalVariable, parentContext: parent, applyTypeRefToSource: (value) => { if (typeof value === "string") { decisionTable["@_typeRef"] = value; } else { decisionTable["@_typeRef"] = value?.typeRef; } }, }); } private addInputVariable(parent: IdentifierContext, requirement: DmnInformationRequirement) { if (requirement.requiredDecision) { parent.inputIdentifiers.push(requirement.requiredDecision["@_href"]?.replace("#", "")); } else if (requirement.requiredInput) { parent.inputIdentifiers.push(requirement.requiredInput["@_href"]?.replace("#", "")); } } private addInputVariableFromKnowledge(parent: IdentifierContext, knowledgeRequirement: DmnKnowledgeRequirement) { if (knowledgeRequirement.requiredKnowledge) { parent.inputIdentifiers.push(knowledgeRequirement.requiredKnowledge["@_href"]?.replace("#", "")); } } private buildIdentifierUuid(uuid: string) { if (this.currentUuidPrefix.length != 0) { return this.currentUuidPrefix + uuid; } return uuid; } private buildName(name: string) { if (this.currentIdentifierNamePrefix.length != 0) { return `${this.currentIdentifierNamePrefix}.${name}`; } return name; } private loadIdentifiers(dmnDefinitions: DmnDefinitions) { this.createDataTypes(dmnDefinitions); this.loadIdentifiersFromDefinitions(dmnDefinitions); } private loadImportedIdentifiers(dmnDefinitions: DmnDefinitions, externalDefinitions?: Map<string, DmnLatestModel>) { if (!(dmnDefinitions.import && externalDefinitions)) { return; } for (const dmnImport of dmnDefinitions.import.filter((imp) => externalDefinitions.has(imp["@_namespace"]))) { this.currentIdentifierNamePrefix = dmnImport["@_name"]; this.currentUuidPrefix = dmnImport["@_namespace"]; const externalDef = externalDefinitions.get(dmnImport["@_namespace"]); if (externalDef) { this.loadIdentifiers(externalDef.definitions); } } } }