node-opcua-address-space 2.81.0 → 2.83.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/source/loader/ensure_datatype_extracted.js +1 -1
- package/dist/source/loader/ensure_datatype_extracted.js.map +1 -1
- package/dist/source/loader/load_nodeset2.js +9 -22
- package/dist/source/loader/load_nodeset2.js.map +1 -1
- package/dist/source/xml_writer.d.ts +5 -1
- package/dist/src/address_space.js +1 -1
- package/dist/src/address_space.js.map +1 -1
- package/dist/src/apply_condition_refresh.d.ts +1 -1
- package/dist/src/apply_condition_refresh.js +5 -5
- package/dist/src/apply_condition_refresh.js.map +1 -1
- package/dist/src/base_node_impl.d.ts +1 -0
- package/dist/src/base_node_impl.js +83 -54
- package/dist/src/base_node_impl.js.map +1 -1
- package/dist/src/base_node_private.d.ts +23 -3
- package/dist/src/base_node_private.js +3 -2
- package/dist/src/base_node_private.js.map +1 -1
- package/dist/src/index_current.d.ts +1 -1
- package/dist/src/index_current.js +2 -3
- package/dist/src/index_current.js.map +1 -1
- package/dist/src/namespace_impl.d.ts +4 -1
- package/dist/src/namespace_impl.js +10 -2
- package/dist/src/namespace_impl.js.map +1 -1
- package/dist/src/namespace_private.d.ts +2 -1
- package/dist/src/namespace_private.js.map +1 -1
- package/dist/src/nodeset_tools/construct_namespace_dependency.d.ts +3 -1
- package/dist/src/nodeset_tools/construct_namespace_dependency.js +35 -5
- package/dist/src/nodeset_tools/construct_namespace_dependency.js.map +1 -1
- package/dist/src/nodeset_tools/nodeset_to_xml.d.ts +4 -2
- package/dist/src/nodeset_tools/nodeset_to_xml.js +44 -59
- package/dist/src/nodeset_tools/nodeset_to_xml.js.map +1 -1
- package/dist/src/ua_data_type_impl.d.ts +2 -0
- package/dist/src/ua_data_type_impl.js +10 -15
- package/dist/src/ua_data_type_impl.js.map +1 -1
- package/dist/src/ua_reference_type_impl.d.ts +1 -1
- package/dist/src/ua_reference_type_impl.js +1 -1
- package/dist/src/ua_reference_type_impl.js.map +1 -1
- package/dist/src/ua_variable_impl.d.ts +2 -0
- package/dist/src/ua_variable_impl.js +49 -11
- package/dist/src/ua_variable_impl.js.map +1 -1
- package/package.json +40 -40
- package/source/loader/ensure_datatype_extracted.ts +1 -1
- package/source/loader/load_nodeset2.ts +22 -36
- package/source/xml_writer.ts +5 -1
- package/src/address_space.ts +1 -2
- package/src/apply_condition_refresh.ts +5 -5
- package/src/base_node_impl.ts +86 -59
- package/src/base_node_private.ts +26 -10
- package/src/index_current.ts +1 -1
- package/src/namespace_impl.ts +13 -3
- package/src/namespace_private.ts +7 -1
- package/src/nodeset_tools/construct_namespace_dependency.ts +42 -5
- package/src/nodeset_tools/nodeset_to_xml.ts +57 -84
- package/src/ua_data_type_impl.ts +12 -15
- package/src/ua_reference_type_impl.ts +2 -2
- package/src/ua_variable_impl.ts +74 -31
- package/test_helpers/test_fixtures/dataType_with_union.xml +90 -1
- package/test_helpers/test_fixtures/datatype_as_per_1.04.xml +38 -10
|
@@ -8,19 +8,23 @@ function _constructNamespaceDependency(
|
|
|
8
8
|
namespace: INamespace,
|
|
9
9
|
dependency: INamespace[],
|
|
10
10
|
depMap: Set<number>,
|
|
11
|
-
_visitedDataType: Set<string
|
|
11
|
+
_visitedDataType: Set<string>,
|
|
12
|
+
priorityTable: number[]
|
|
12
13
|
): void {
|
|
13
14
|
const addressSpace = namespace.addressSpace;
|
|
14
15
|
const namespace_ = namespace as NamespacePrivate;
|
|
15
16
|
// navigate all namespace recursively to
|
|
16
17
|
|
|
17
18
|
function consider(namespaceIndex: number) {
|
|
19
|
+
if (hasHigherPriorityThan(namespaceIndex,namespace.index, priorityTable)) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
18
22
|
if (!depMap.has(namespaceIndex)) {
|
|
19
23
|
depMap.add(namespaceIndex);
|
|
20
24
|
const namespace = addressSpace.getNamespace(namespaceIndex);
|
|
21
25
|
dependency.push(namespace);
|
|
22
26
|
if (namespaceIndex > 0) {
|
|
23
|
-
_constructNamespaceDependency(namespace, dependency, depMap, _visitedDataType);
|
|
27
|
+
_constructNamespaceDependency(namespace, dependency, depMap, _visitedDataType, priorityTable);
|
|
24
28
|
}
|
|
25
29
|
}
|
|
26
30
|
}
|
|
@@ -57,7 +61,7 @@ function _constructNamespaceDependency(
|
|
|
57
61
|
exploreDataTypes(dataTypeNode);
|
|
58
62
|
} else {
|
|
59
63
|
// istanbul ignore next
|
|
60
|
-
if (dataTypeNodeId.value!=0) {
|
|
64
|
+
if (dataTypeNodeId.value != 0) {
|
|
61
65
|
console.log("Internal error: Cannot find dataType", dataTypeNodeId.toString());
|
|
62
66
|
}
|
|
63
67
|
}
|
|
@@ -74,8 +78,41 @@ function _constructNamespaceDependency(
|
|
|
74
78
|
}
|
|
75
79
|
}
|
|
76
80
|
|
|
77
|
-
|
|
81
|
+
|
|
82
|
+
export function hasHigherPriorityThan(namespaceIndex1: number, namespaceIndex2: number, priorityTable: number[]) {
|
|
83
|
+
const order1 = priorityTable[namespaceIndex1];
|
|
84
|
+
const order2 = priorityTable[namespaceIndex2];
|
|
85
|
+
return order1 > order2;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function constructNamespacePriorityTable(namespace: INamespace): number[] {
|
|
89
|
+
|
|
90
|
+
// Namespace 0 will always be 0
|
|
91
|
+
// Namespaces with no requiredModel will be considered as instance namespaces and will added at the end
|
|
92
|
+
// in the same order as they appear,
|
|
93
|
+
// Namespace with requiredModels are considered to be companion specification, so already loaded in the correct order
|
|
94
|
+
|
|
95
|
+
const addressSpace = namespace.addressSpace;
|
|
96
|
+
const namespaces = addressSpace.getNamespaceArray();
|
|
97
|
+
|
|
98
|
+
const namespaceWithReq = namespaces.filter((n)=> (n.getRequiredModels() !== undefined) && n.index !==0);
|
|
99
|
+
const namespaceWithoutReq = namespaces.filter((n)=>(n.getRequiredModels() === undefined) && n.index !==0);
|
|
100
|
+
|
|
101
|
+
const priorityList: number[] = [0];
|
|
102
|
+
let counter = 1;
|
|
103
|
+
for (let i = 0; i < namespaceWithReq.length; i++) {
|
|
104
|
+
priorityList[namespaceWithReq[i].index] = counter++;
|
|
105
|
+
}
|
|
106
|
+
for (let i = 0; i < namespaceWithoutReq.length; i++) {
|
|
107
|
+
priorityList[namespaceWithoutReq[i].index] = counter++;
|
|
108
|
+
}
|
|
109
|
+
return priorityList;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function constructNamespaceDependency(namespace: INamespace, priorityTable?: number[]): INamespace[] {
|
|
78
113
|
const addressSpace = namespace.addressSpace;
|
|
114
|
+
|
|
115
|
+
priorityTable = priorityTable || constructNamespacePriorityTable(namespace);
|
|
79
116
|
|
|
80
117
|
const dependency: INamespace[] = [];
|
|
81
118
|
const depMap = new Set<number>();
|
|
@@ -89,7 +126,7 @@ export function constructNamespaceDependency(namespace: INamespace): INamespace[
|
|
|
89
126
|
}
|
|
90
127
|
const _visitedDataType = new Set<string>();
|
|
91
128
|
|
|
92
|
-
_constructNamespaceDependency(namespace, dependency, depMap, _visitedDataType);
|
|
129
|
+
_constructNamespaceDependency(namespace, dependency, depMap, _visitedDataType, priorityTable);
|
|
93
130
|
|
|
94
131
|
return dependency;
|
|
95
132
|
}
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
import { AttributeIds, Int64, minOPCUADate, StatusCode, StatusCodes } from "node-opcua-basic-types";
|
|
35
35
|
import { BrowseDescription, EnumDefinition, StructureDefinition, StructureType } from "node-opcua-types";
|
|
36
36
|
|
|
37
|
-
import { XmlWriter } from "../../source/xml_writer";
|
|
37
|
+
import { ITranslationTable, XmlWriter } from "../../source/xml_writer";
|
|
38
38
|
import { NamespacePrivate } from "../namespace_private";
|
|
39
39
|
import { ReferenceImpl } from "../reference_impl";
|
|
40
40
|
import { BaseNodeImpl, getReferenceType } from "../base_node_impl";
|
|
@@ -50,7 +50,7 @@ import { SessionContext } from "../index_current";
|
|
|
50
50
|
|
|
51
51
|
import { DefinitionMap2, TypeInfo } from "../../source/loader/make_xml_extension_object_parser";
|
|
52
52
|
import { makeDefinitionMap } from "../../source/loader/decode_xml_extension_object";
|
|
53
|
-
import { constructNamespaceDependency } from "./construct_namespace_dependency";
|
|
53
|
+
import { constructNamespaceDependency, constructNamespacePriorityTable, hasHigherPriorityThan } from "./construct_namespace_dependency";
|
|
54
54
|
|
|
55
55
|
// tslint:disable:no-var-requires
|
|
56
56
|
const XMLWriter = require("xml-writer");
|
|
@@ -98,17 +98,20 @@ function b(xw: XmlWriter, browseName: QualifiedName): string {
|
|
|
98
98
|
return translateBrowseName(xw, browseName).toString().replace("ns=0;", "");
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
function _hasHigherPriorityThan(xw: XmlWriter, namespaceIndex1: number, namespaceIndex2: number) {
|
|
102
|
+
assert(xw.priorityTable, "expecting a priorityTable");
|
|
103
|
+
assert(namespaceIndex1 < xw.priorityTable.length);
|
|
104
|
+
assert(namespaceIndex2 < xw.priorityTable.length);
|
|
105
|
+
return hasHigherPriorityThan(namespaceIndex1, namespaceIndex2, xw.priorityTable);
|
|
104
106
|
}
|
|
107
|
+
|
|
105
108
|
function _dumpReferences(xw: XmlWriter, node: BaseNode) {
|
|
106
109
|
xw.startElement("References");
|
|
107
110
|
|
|
108
111
|
const addressSpace = node.addressSpace;
|
|
109
112
|
|
|
110
113
|
const aggregateReferenceType = addressSpace.findReferenceType("Aggregates")!;
|
|
111
|
-
const hasChildReferenceType = addressSpace.findReferenceType("HasChild")!;
|
|
114
|
+
// const hasChildReferenceType = addressSpace.findReferenceType("HasChild")!;
|
|
112
115
|
const hasSubtypeReferenceType = addressSpace.findReferenceType("HasSubtype")!;
|
|
113
116
|
const hasTypeDefinitionReferenceType = addressSpace.findReferenceType("HasTypeDefinition")!;
|
|
114
117
|
const nonHierarchicalReferencesType = addressSpace.findReferenceType("NonHierarchicalReferences")!;
|
|
@@ -119,6 +122,13 @@ function _dumpReferences(xw: XmlWriter, node: BaseNode) {
|
|
|
119
122
|
function referenceToKeep(reference: UAReference): boolean {
|
|
120
123
|
const referenceType = (reference as ReferenceImpl)._referenceType!;
|
|
121
124
|
|
|
125
|
+
const targetedNamespaceIndex = reference.nodeId.namespace;
|
|
126
|
+
if (_hasHigherPriorityThan(xw, targetedNamespaceIndex, node.nodeId.namespace)) {
|
|
127
|
+
// this reference has nothing to do here ! drop it
|
|
128
|
+
// because the target namespace is higher in the hierarchy
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
|
|
122
132
|
// get the direct backward reference to a external namespace
|
|
123
133
|
if (referenceType.isSupertypeOf(aggregateReferenceType) && !reference.isForward) {
|
|
124
134
|
if (reference.nodeId.namespace !== node.nodeId.namespace) {
|
|
@@ -128,7 +138,9 @@ function _dumpReferences(xw: XmlWriter, node: BaseNode) {
|
|
|
128
138
|
return true;
|
|
129
139
|
}
|
|
130
140
|
}
|
|
131
|
-
|
|
141
|
+
if (referenceType.isSupertypeOf(hasSubtypeReferenceType) && reference.isForward) {
|
|
142
|
+
// return false;
|
|
143
|
+
}
|
|
132
144
|
// only keep
|
|
133
145
|
if (referenceType.isSupertypeOf(aggregateReferenceType) && reference.isForward) {
|
|
134
146
|
return true;
|
|
@@ -154,8 +166,6 @@ function _dumpReferences(xw: XmlWriter, node: BaseNode) {
|
|
|
154
166
|
if (getReferenceType(reference).browseName.toString() === "HasSubtype" && reference.isForward) {
|
|
155
167
|
continue;
|
|
156
168
|
}
|
|
157
|
-
|
|
158
|
-
// only output inverse Reference
|
|
159
169
|
xw.startElement("Reference");
|
|
160
170
|
|
|
161
171
|
xw.writeAttribute("ReferenceType", b(xw, getReferenceType(reference).browseName));
|
|
@@ -665,7 +675,6 @@ function _dumpArrayDimensionsAttribute(xw: XmlWriter, node: UAVariableType | UAV
|
|
|
665
675
|
}
|
|
666
676
|
|
|
667
677
|
function visitUANode(node: BaseNode, data: DumpData, forward: boolean) {
|
|
668
|
-
assert(typeof forward === "boolean");
|
|
669
678
|
|
|
670
679
|
const addressSpace = node.addressSpace;
|
|
671
680
|
|
|
@@ -772,7 +781,9 @@ function dumpCommonAttributes(xw: XmlWriter, node: BaseNode) {
|
|
|
772
781
|
|
|
773
782
|
const parentNode = getParent(node);
|
|
774
783
|
if (parentNode) {
|
|
775
|
-
|
|
784
|
+
if (parentNode.nodeId.namespace <= node.nodeId.namespace) {
|
|
785
|
+
xw.writeAttribute("ParentNodeId", n(xw, parentNode.nodeId));
|
|
786
|
+
}
|
|
776
787
|
}
|
|
777
788
|
if (Object.prototype.hasOwnProperty.call(node, "symbolicName")) {
|
|
778
789
|
xw.writeAttribute("SymbolicName", (node as any).symbolicName);
|
|
@@ -788,6 +799,12 @@ function dumpCommonAttributes(xw: XmlWriter, node: BaseNode) {
|
|
|
788
799
|
xw.writeAttribute("AccessLevel", (node as UAVariable).accessLevel.toString());
|
|
789
800
|
}
|
|
790
801
|
}
|
|
802
|
+
if (Object.prototype.hasOwnProperty.call(node, "minimumSamplingInterval")) {
|
|
803
|
+
const minimumSamplingInterval =(node as UAVariable).minimumSamplingInterval;
|
|
804
|
+
if (minimumSamplingInterval > 0) {
|
|
805
|
+
xw.writeAttribute("MinimumSamplingInterval", minimumSamplingInterval);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
791
808
|
}
|
|
792
809
|
|
|
793
810
|
function dumpCommonElements(xw: XmlWriter, node: BaseNode) {
|
|
@@ -800,11 +817,11 @@ function coerceInt64ToInt32(int64: Int64): number {
|
|
|
800
817
|
if (typeof int64 === "number") {
|
|
801
818
|
return int64 as number;
|
|
802
819
|
}
|
|
803
|
-
if (int64[0] ===
|
|
820
|
+
if (int64[0] === 0xffffffff && int64[1] === 0xffffffff) {
|
|
804
821
|
return 0xffffffff;
|
|
805
822
|
}
|
|
806
823
|
if (int64[0] !== 0) {
|
|
807
|
-
|
|
824
|
+
warningLog("coerceInt64ToInt32 , loosing high word in conversion");
|
|
808
825
|
}
|
|
809
826
|
return int64[1];
|
|
810
827
|
}
|
|
@@ -831,8 +848,8 @@ function _dumpStructureDefinition(
|
|
|
831
848
|
* note: baseDataType and defaultEncodingId are implicit and not stored in the XML file ??
|
|
832
849
|
*
|
|
833
850
|
*/
|
|
834
|
-
const baseDataType = structureDefinition.baseDataType;
|
|
835
|
-
const defaultEncodingId = structureDefinition.defaultEncodingId;
|
|
851
|
+
// const baseDataType = structureDefinition.baseDataType;
|
|
852
|
+
// const defaultEncodingId = structureDefinition.defaultEncodingId;
|
|
836
853
|
|
|
837
854
|
// do not repeat elements that are already defined in base structure in the xml ouput!
|
|
838
855
|
const fields = structureDefinition.fields || [];
|
|
@@ -927,9 +944,7 @@ function dumpUADataType(xw: XmlWriter, node: UADataType) {
|
|
|
927
944
|
xw.writeAttribute("IsAbstract", node.isAbstract ? "true" : "false");
|
|
928
945
|
}
|
|
929
946
|
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
_dumpReferences(xw, node);
|
|
947
|
+
dumpCommonElements(xw, node);
|
|
933
948
|
|
|
934
949
|
_dumpUADataTypeDefinition(xw, node);
|
|
935
950
|
|
|
@@ -1015,11 +1030,11 @@ function dumpUAVariableType(xw: XmlWriter, node: UAVariableType) {
|
|
|
1015
1030
|
// throw new Error(" cannot find datatype " + node.dataType);
|
|
1016
1031
|
console.log(
|
|
1017
1032
|
" cannot find datatype " +
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1033
|
+
node.dataType +
|
|
1034
|
+
" for node " +
|
|
1035
|
+
node.browseName.toString() +
|
|
1036
|
+
" id =" +
|
|
1037
|
+
node.nodeId.toString()
|
|
1023
1038
|
);
|
|
1024
1039
|
} else {
|
|
1025
1040
|
const dataTypeName = b(xw, resolveDataTypeName(addressSpace, dataTypeNode.nodeId));
|
|
@@ -1088,11 +1103,18 @@ function dumpAggregates(xw: XmlWriter, node: BaseNode) {
|
|
|
1088
1103
|
// Xx xw.writeComment("Aggregates {{ ");
|
|
1089
1104
|
const aggregates = node
|
|
1090
1105
|
.getAggregates()
|
|
1091
|
-
.sort(
|
|
1106
|
+
.sort(sortByBrowseName);
|
|
1107
|
+
// const aggregates = node.findReferencesExAsObject("Aggregates", BrowseDirection.Forward);
|
|
1108
|
+
|
|
1092
1109
|
for (const aggregate of aggregates.sort(sortByNodeId)) {
|
|
1093
1110
|
// do not export node that do not belong to our namespace
|
|
1094
1111
|
if (node.nodeId.namespace !== aggregate.nodeId.namespace) {
|
|
1095
|
-
|
|
1112
|
+
continue;
|
|
1113
|
+
}
|
|
1114
|
+
// even further! we should export here the children
|
|
1115
|
+
// that have been added later by a namespace with higher index
|
|
1116
|
+
if (_hasHigherPriorityThan(xw, aggregate.nodeId.namespace, node.nodeId.namespace)) {
|
|
1117
|
+
continue;
|
|
1096
1118
|
}
|
|
1097
1119
|
if (!xw.visitedNode[_hash(aggregate)]) {
|
|
1098
1120
|
(<BaseNodeImpl>aggregate).dumpXML(xw);
|
|
@@ -1219,18 +1241,15 @@ function writeAliases(xw: XmlWriter, aliases: Record<string, NodeIdString>) {
|
|
|
1219
1241
|
}
|
|
1220
1242
|
xw.endElement();
|
|
1221
1243
|
}
|
|
1222
|
-
interface ITranslationTable {
|
|
1223
|
-
[key: number]: number;
|
|
1224
|
-
}
|
|
1225
1244
|
|
|
1226
|
-
|
|
1245
|
+
|
|
1246
|
+
export function constructNamespaceTranslationTable(dependency: INamespace[]): ITranslationTable {
|
|
1227
1247
|
const translationTable: ITranslationTable = {};
|
|
1228
1248
|
for (let i = 0; i < dependency.length; i++) {
|
|
1229
1249
|
translationTable[dependency[i].index] = i;
|
|
1230
1250
|
}
|
|
1231
1251
|
return translationTable;
|
|
1232
1252
|
}
|
|
1233
|
-
|
|
1234
1253
|
function dumpReferenceType(xw: XmlWriter, referenceType: UAReferenceType) {
|
|
1235
1254
|
_markAsVisited(xw, referenceType);
|
|
1236
1255
|
|
|
@@ -1249,7 +1268,7 @@ function dumpReferenceType(xw: XmlWriter, referenceType: UAReferenceType) {
|
|
|
1249
1268
|
xw.endElement();
|
|
1250
1269
|
}
|
|
1251
1270
|
|
|
1252
|
-
function sortByBrowseName(x: BaseNode, y: BaseNode): number {
|
|
1271
|
+
export function sortByBrowseName(x: BaseNode, y: BaseNode): number {
|
|
1253
1272
|
const x_str = x.browseName.toString();
|
|
1254
1273
|
const y_str = y.browseName.toString();
|
|
1255
1274
|
if (x_str > y_str) {
|
|
@@ -1281,56 +1300,6 @@ export interface DumpXMLOptions {
|
|
|
1281
1300
|
/** */
|
|
1282
1301
|
}
|
|
1283
1302
|
|
|
1284
|
-
export function dumpXml(node: BaseNode, options: DumpXMLOptions): void {
|
|
1285
|
-
const namespace = node.namespace as NamespacePrivate;
|
|
1286
|
-
|
|
1287
|
-
// make a first visit so that we determine which node to output and in which order
|
|
1288
|
-
const data: DumpData = { aliases: {}, aliases_visited: {}, index_el: {}, elements: [] };
|
|
1289
|
-
|
|
1290
|
-
const dependency = constructNamespaceDependency(namespace);
|
|
1291
|
-
const translationTable = constructNamespaceTranslationTable(dependency);
|
|
1292
|
-
|
|
1293
|
-
const xw = new XMLWriter(true);
|
|
1294
|
-
xw.translationTable = translationTable;
|
|
1295
|
-
|
|
1296
|
-
visitUANode(node, data, false);
|
|
1297
|
-
|
|
1298
|
-
xw.startDocument({ encoding: "utf-8" });
|
|
1299
|
-
xw.startElement("UANodeSet");
|
|
1300
|
-
xw.writeAttribute("xmlns:xs", "http://www.w3.org/2001/XMLSchema-instance");
|
|
1301
|
-
xw.writeAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
|
|
1302
|
-
xw.writeAttribute("Version", "1.02");
|
|
1303
|
-
xw.writeAttribute("LastModified", new Date().toISOString());
|
|
1304
|
-
xw.writeAttribute("xmlns", "http://opcfoundation.org/UA/2011/03/UANodeSet.xsd");
|
|
1305
|
-
|
|
1306
|
-
buildUpAliases(node, xw, data);
|
|
1307
|
-
writeAliases(xw, data.aliases);
|
|
1308
|
-
|
|
1309
|
-
const xmlNamspace = {
|
|
1310
|
-
default: { namespace: "http://opcfoundation.org/UA/2011/03/UANodeSet.xsd" }
|
|
1311
|
-
};
|
|
1312
|
-
|
|
1313
|
-
xw.startElement("Extensions");
|
|
1314
|
-
{
|
|
1315
|
-
xw.startElement("Extension");
|
|
1316
|
-
{
|
|
1317
|
-
xw.startElement("ModelInfo");
|
|
1318
|
-
xw.writeAttribute("NodeOPCUA");
|
|
1319
|
-
xw.endElement();
|
|
1320
|
-
}
|
|
1321
|
-
xw.endElement();
|
|
1322
|
-
}
|
|
1323
|
-
xw.endElement();
|
|
1324
|
-
|
|
1325
|
-
for (const el of data.elements!) {
|
|
1326
|
-
el.dumpXML(xw);
|
|
1327
|
-
}
|
|
1328
|
-
|
|
1329
|
-
xw.endElement();
|
|
1330
|
-
xw.endDocument();
|
|
1331
|
-
return xw.toString();
|
|
1332
|
-
}
|
|
1333
|
-
|
|
1334
1303
|
UAMethodImpl.prototype.dumpXML = function (xw) {
|
|
1335
1304
|
dumpUAMethod(xw, this);
|
|
1336
1305
|
};
|
|
@@ -1360,17 +1329,21 @@ function makeTypeXsd(namespaceUri: string): string {
|
|
|
1360
1329
|
|
|
1361
1330
|
// eslint-disable-next-line max-statements
|
|
1362
1331
|
NamespaceImpl.prototype.toNodeset2XML = function (this: NamespaceImpl) {
|
|
1363
|
-
|
|
1364
|
-
const translationTable = constructNamespaceTranslationTable(dependency);
|
|
1332
|
+
|
|
1365
1333
|
|
|
1366
1334
|
const namespaceArrayNode = this.addressSpace.findNode(VariableIds.Server_NamespaceArray);
|
|
1367
1335
|
const namespaceArray: string[] = namespaceArrayNode
|
|
1368
1336
|
? namespaceArrayNode.readAttribute(null, AttributeIds.Value).value.value
|
|
1369
1337
|
: [];
|
|
1370
1338
|
|
|
1371
|
-
const xw = new XMLWriter(true);
|
|
1339
|
+
const xw: XmlWriter = new XMLWriter(true);
|
|
1340
|
+
|
|
1341
|
+
xw.priorityTable = constructNamespacePriorityTable(this);
|
|
1342
|
+
const dependency = constructNamespaceDependency(this, xw.priorityTable);
|
|
1343
|
+
const translationTable = constructNamespaceTranslationTable(dependency);
|
|
1372
1344
|
xw.translationTable = translationTable;
|
|
1373
1345
|
|
|
1346
|
+
|
|
1374
1347
|
xw.startDocument({ encoding: "utf-8", version: "1.0" });
|
|
1375
1348
|
xw.startElement("UANodeSet");
|
|
1376
1349
|
|
package/src/ua_data_type_impl.ts
CHANGED
|
@@ -31,7 +31,6 @@ import { get_subtypeOf } from "./tool_isSupertypeOf";
|
|
|
31
31
|
import { get_subtypeOfObj } from "./tool_isSupertypeOf";
|
|
32
32
|
import { BaseNode_getCache } from "./base_node_private";
|
|
33
33
|
|
|
34
|
-
|
|
35
34
|
export interface UADataTypeImpl {
|
|
36
35
|
_extensionObjectConstructor: ExtensionObjectConstructorFuncWithSchema;
|
|
37
36
|
}
|
|
@@ -46,6 +45,7 @@ export interface EnumerationInfo {
|
|
|
46
45
|
}
|
|
47
46
|
export interface UADataTypeOptions extends InternalBaseNodeOptions {
|
|
48
47
|
partialDefinition: StructureFieldOptions[] | EnumFieldOptions[];
|
|
48
|
+
isUnion?: boolean;
|
|
49
49
|
isAbstract?: boolean;
|
|
50
50
|
symbolicName?: string;
|
|
51
51
|
}
|
|
@@ -78,6 +78,7 @@ export class UADataTypeImpl extends BaseNodeImpl implements UADataType {
|
|
|
78
78
|
|
|
79
79
|
public readonly isAbstract: boolean;
|
|
80
80
|
|
|
81
|
+
private $isUnion?: boolean;
|
|
81
82
|
private enumStrings?: any;
|
|
82
83
|
private enumValues?: any;
|
|
83
84
|
private $partialDefinition?: StructureFieldOptions[] | EnumFieldOptions[];
|
|
@@ -87,6 +88,7 @@ export class UADataTypeImpl extends BaseNodeImpl implements UADataType {
|
|
|
87
88
|
super(options);
|
|
88
89
|
if (options.partialDefinition) {
|
|
89
90
|
this.$partialDefinition = options.partialDefinition;
|
|
91
|
+
this.$isUnion = options.isUnion;
|
|
90
92
|
}
|
|
91
93
|
this.isAbstract = options.isAbstract === undefined || options.isAbstract === null ? false : options.isAbstract;
|
|
92
94
|
this.symbolicName = options.symbolicName || this.browseName.name!;
|
|
@@ -146,8 +148,9 @@ export class UADataTypeImpl extends BaseNodeImpl implements UADataType {
|
|
|
146
148
|
|
|
147
149
|
public getEncodingNode(encoding_name: string): UAObject | null {
|
|
148
150
|
const _cache = BaseNode_getCache(this);
|
|
151
|
+
_cache._encoding = _cache._encoding || {};
|
|
149
152
|
const key = encoding_name + "Node";
|
|
150
|
-
if (_cache[key] === undefined) {
|
|
153
|
+
if (_cache._encoding[key] === undefined) {
|
|
151
154
|
assert(encoding_name === "Default Binary" || encoding_name === "Default XML" || encoding_name === "Default JSON");
|
|
152
155
|
// could be binary or xml
|
|
153
156
|
const refs = this.findReferences("HasEncoding", true);
|
|
@@ -157,24 +160,18 @@ export class UADataTypeImpl extends BaseNodeImpl implements UADataType {
|
|
|
157
160
|
.filter((obj: any) => obj !== null)
|
|
158
161
|
.filter((obj: any) => obj.browseName.toString() === encoding_name);
|
|
159
162
|
const node = encoding.length === 0 ? null : (encoding[0] as UAObject);
|
|
160
|
-
_cache[key] = node;
|
|
163
|
+
_cache._encoding[key] = node;
|
|
161
164
|
}
|
|
162
|
-
return _cache[key];
|
|
165
|
+
return _cache._encoding[key];
|
|
163
166
|
}
|
|
164
167
|
|
|
165
168
|
public getEncodingNodeId(encoding_name: string): ExpandedNodeId | null {
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const encoding = this.getEncodingNode(encoding_name);
|
|
170
|
-
if (encoding) {
|
|
171
|
-
const namespaceUri = this.addressSpace.getNamespaceUri(encoding.nodeId.namespace);
|
|
172
|
-
_cache[key] = ExpandedNodeId.fromNodeId(encoding.nodeId, namespaceUri);
|
|
173
|
-
} else {
|
|
174
|
-
_cache[key] = null;
|
|
175
|
-
}
|
|
169
|
+
const encoding = this.getEncodingNode(encoding_name);
|
|
170
|
+
if (!encoding) {
|
|
171
|
+
return null;
|
|
176
172
|
}
|
|
177
|
-
|
|
173
|
+
const namespaceUri = this.addressSpace.getNamespaceUri(encoding.nodeId.namespace);
|
|
174
|
+
return ExpandedNodeId.fromNodeId(encoding.nodeId, namespaceUri);
|
|
178
175
|
}
|
|
179
176
|
/**
|
|
180
177
|
* returns the encoding of this node's
|
|
@@ -56,7 +56,7 @@ function _getAllSubtypes(ref: UAReferenceType) {
|
|
|
56
56
|
function _internal_getSubtypeIndex(referenceType: UAReferenceType): { [key: string]: UAReferenceTypePublic } {
|
|
57
57
|
const possibleReferenceTypes = _getAllSubtypes(referenceType);
|
|
58
58
|
// create a index of reference type with browseName as key for faster search
|
|
59
|
-
const keys:
|
|
59
|
+
const keys: Record<string, UAReferenceType> = {};
|
|
60
60
|
for (const refType of possibleReferenceTypes) {
|
|
61
61
|
keys[refType.nodeId.toString()] = refType;
|
|
62
62
|
}
|
|
@@ -65,7 +65,7 @@ function _internal_getSubtypeIndex(referenceType: UAReferenceType): { [key: stri
|
|
|
65
65
|
|
|
66
66
|
function _getSubtypeIndex(referenceType: UAReferenceType): { [key: string]: UAReferenceTypePublic } {
|
|
67
67
|
const _cache = BaseNode_getCache(referenceType);
|
|
68
|
-
if (!_cache._subtype_idx || _cache._subtype_idxVersion < ReferenceTypeCounter.count) {
|
|
68
|
+
if (!_cache._subtype_idx || (_cache._subtype_idxVersion && _cache._subtype_idxVersion < ReferenceTypeCounter.count)) {
|
|
69
69
|
// the cache need to be invalidated
|
|
70
70
|
_cache._subtype_idx = null;
|
|
71
71
|
}
|