node-opcua-address-space 2.116.0 → 2.118.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.
Files changed (57) hide show
  1. package/dist/source/loader/generateAddressSpaceRaw.js +8 -4
  2. package/dist/source/loader/generateAddressSpaceRaw.js.map +1 -1
  3. package/dist/source/loader/load_nodeset2.js +2 -2
  4. package/dist/source/loader/load_nodeset2.js.map +1 -1
  5. package/dist/source/pseudo_session.js +12 -26
  6. package/dist/source/pseudo_session.js.map +1 -1
  7. package/dist/src/address_space.js +4 -27
  8. package/dist/src/address_space.js.map +1 -1
  9. package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js +2 -25
  10. package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js.map +1 -1
  11. package/dist/src/base_node_impl.js +2 -25
  12. package/dist/src/base_node_impl.js.map +1 -1
  13. package/dist/src/namespace_impl.js +3 -26
  14. package/dist/src/namespace_impl.js.map +1 -1
  15. package/dist/src/nodeset_tools/construct_namespace_dependency.d.ts +27 -3
  16. package/dist/src/nodeset_tools/construct_namespace_dependency.js +210 -81
  17. package/dist/src/nodeset_tools/construct_namespace_dependency.js.map +1 -1
  18. package/dist/src/nodeset_tools/nodeset_to_xml.js +18 -49
  19. package/dist/src/nodeset_tools/nodeset_to_xml.js.map +1 -1
  20. package/dist/src/reference_impl.js +2 -25
  21. package/dist/src/reference_impl.js.map +1 -1
  22. package/dist/src/ua_data_type_impl.d.ts +2 -3
  23. package/dist/src/ua_data_type_impl.js +6 -29
  24. package/dist/src/ua_data_type_impl.js.map +1 -1
  25. package/dist/src/ua_object_type_impl.d.ts +2 -3
  26. package/dist/src/ua_object_type_impl.js +4 -28
  27. package/dist/src/ua_object_type_impl.js.map +1 -1
  28. package/dist/src/ua_reference_type_impl.d.ts +2 -3
  29. package/dist/src/ua_reference_type_impl.js +6 -29
  30. package/dist/src/ua_reference_type_impl.js.map +1 -1
  31. package/dist/src/ua_variable_impl.js +3 -26
  32. package/dist/src/ua_variable_impl.js.map +1 -1
  33. package/dist/src/ua_variable_type_impl.d.ts +2 -3
  34. package/dist/src/ua_variable_type_impl.js +5 -28
  35. package/dist/src/ua_variable_type_impl.js.map +1 -1
  36. package/dist/tsconfig_common.tsbuildinfo +1 -1
  37. package/distHelpers/get_address_space_fixture.js +16 -36
  38. package/distHelpers/get_address_space_fixture.js.map +1 -1
  39. package/distNodeJS/generate_address_space.js +5 -25
  40. package/distNodeJS/generate_address_space.js.map +1 -1
  41. package/package.json +40 -40
  42. package/source/loader/generateAddressSpaceRaw.ts +10 -4
  43. package/source/loader/load_nodeset2.ts +2 -2
  44. package/source/pseudo_session.ts +8 -2
  45. package/source_nodejs/generate_address_space.ts +1 -1
  46. package/src/address_space.ts +2 -2
  47. package/src/alarms_and_conditions/ua_off_normal_alarm_impl.ts +2 -4
  48. package/src/base_node_impl.ts +2 -2
  49. package/src/namespace_impl.ts +5 -7
  50. package/src/nodeset_tools/construct_namespace_dependency.ts +232 -91
  51. package/src/nodeset_tools/nodeset_to_xml.ts +21 -30
  52. package/src/reference_impl.ts +2 -2
  53. package/src/ua_data_type_impl.ts +14 -15
  54. package/src/ua_object_type_impl.ts +6 -6
  55. package/src/ua_reference_type_impl.ts +4 -4
  56. package/src/ua_variable_impl.ts +4 -6
  57. package/src/ua_variable_type_impl.ts +3 -3
@@ -1,4 +1,4 @@
1
- import { INamespace, UADataType, UAVariable, UAVariableType } from "node-opcua-address-space-base";
1
+ import { IAddressSpace, INamespace, UADataType, UAVariable, UAVariableType } from "node-opcua-address-space-base";
2
2
  import { NodeClass } from "node-opcua-data-model";
3
3
  import { StructureField } from "node-opcua-types";
4
4
  import { DataType } from "node-opcua-basic-types";
@@ -9,42 +9,46 @@ import { make_debugLog, make_warningLog } from "node-opcua-debug";
9
9
  import { NamespacePrivate } from "../namespace_private";
10
10
  import { BaseNodeImpl, getReferenceType } from "../base_node_impl";
11
11
  import { UAVariableImpl } from "../ua_variable_impl";
12
+ import { ITranslationTable } from "../../source/xml_writer";
12
13
 
13
14
  const warningLog = make_warningLog(__filename);
14
15
  const debugLog = make_debugLog(__filename);
15
16
 
16
- function _constructNamespaceDependency(
17
+ // eslint-disable-next-line max-statements, complexity
18
+ export function _recomputeRequiredModelsFromTypes(
17
19
  namespace: INamespace,
18
- dependency: INamespace[],
19
- depMap: Set<number>,
20
- _visitedDataType: Set<string>,
21
- priorityTable: number[]
22
- ): void {
23
- const addressSpace = namespace.addressSpace;
24
- const namespace_ = namespace as NamespacePrivate;
25
- // navigate all namespace recursively to
26
-
27
- function consider(namespaceIndex: number) {
28
- if (hasHigherPriorityThan(namespaceIndex, namespace.index, priorityTable)) {
29
- return;
30
- }
31
- considerStrongly(namespaceIndex);
20
+ cache?: Map<number, { requiredNamespaceIndexes: number[]; nbTypes: number }>
21
+ ): { requiredNamespaceIndexes: number[]; nbTypes: number } {
22
+ if (namespace.index === 0) {
23
+ return { requiredNamespaceIndexes: [], nbTypes: 1 };
32
24
  }
33
- function considerStrongly(namespaceIndex: number) {
34
- if (!depMap.has(namespaceIndex)) {
35
- depMap.add(namespaceIndex);
36
- const namespace = addressSpace.getNamespace(namespaceIndex);
37
- dependency.push(namespace);
38
- if (namespaceIndex > 0) {
39
- _constructNamespaceDependency(namespace, dependency, depMap, _visitedDataType, priorityTable);
40
- }
25
+ if (cache) {
26
+ if (cache.has(namespace.index)) {
27
+ return cache.get(namespace.index)!;
41
28
  }
42
29
  }
30
+ const requiredNamespaceIndexes = [0];
31
+ const requiredModelsSet = new Set<number>();
32
+ requiredModelsSet.add(0);
33
+ const namespace_ = namespace as NamespacePrivate;
34
+ let nbTypes = 0;
35
+ const addressSpace = namespace.addressSpace;
36
+ const types = [NodeClass.VariableType, NodeClass.ObjectType, NodeClass.ReferenceType, NodeClass.DataType];
37
+ const instances = [NodeClass.Variable, NodeClass.Object, NodeClass.Method];
38
+
39
+ const consider = (requiredModel: number) => {
40
+ if (requiredModel !== namespace.index && !requiredModelsSet.has(requiredModel)) {
41
+ requiredModelsSet.add(requiredModel);
42
+ requiredNamespaceIndexes.push(requiredModel);
43
+ }
44
+ };
45
+
46
+ const _visitedDataType: Set<string> = new Set<string>();
43
47
 
44
48
  function exploreDataTypeField(field: StructureField) {
45
49
  const dataType = field.dataType;
46
50
  const namespaceIndex = dataType.namespace;
47
- considerStrongly(namespaceIndex);
51
+ consider(namespaceIndex);
48
52
  const dataTypeNode = addressSpace.findDataType(field.dataType);
49
53
  if (dataTypeNode) {
50
54
  exploreDataTypes(dataTypeNode);
@@ -65,7 +69,7 @@ function _constructNamespaceDependency(
65
69
  }
66
70
 
67
71
  const namespaceIndex = dataType.namespace;
68
- considerStrongly(namespaceIndex);
72
+ consider(namespaceIndex);
69
73
  if (dataTypeNode.isStructure()) {
70
74
  const definition = dataTypeNode.getStructureDefinition();
71
75
  for (const field of definition.fields || []) {
@@ -78,7 +82,7 @@ function _constructNamespaceDependency(
78
82
  function exploreExtensionObject(e: ExtensionObject) {
79
83
  assert(!(e instanceof Variant));
80
84
  const nodeId = e.schema.encodingDefaultXml || e.schema.dataTypeNodeId || e.schema.dataTypeNodeId;
81
- considerStrongly(nodeId.namespace);
85
+ consider(nodeId.namespace);
82
86
  // istanbul ignore next
83
87
  if (e.schema.dataTypeNodeId.isEmpty()) {
84
88
  warningLog("Cannot find dataTypeNodeId for ", e.schema.name);
@@ -88,6 +92,7 @@ function _constructNamespaceDependency(
88
92
  if (!d) return;
89
93
  exploreDataTypes(d);
90
94
  }
95
+
91
96
  function exploreDataValue(uaVariable: UAVariableImpl) {
92
97
  if (uaVariable.getBasicDataType() !== DataType.ExtensionObject) {
93
98
  return;
@@ -104,36 +109,131 @@ function _constructNamespaceDependency(
104
109
  }
105
110
  }
106
111
  for (const node of namespace_.nodeIterator()) {
107
- if (node.nodeClass === NodeClass.Variable || node.nodeClass === NodeClass.VariableType) {
108
- const dataTypeNodeId = (node as UAVariable | UAVariableType).dataType;
109
- const dataTypeNode = addressSpace.findDataType(dataTypeNodeId)!;
110
- if (dataTypeNode) {
111
- exploreDataTypes(dataTypeNode);
112
- } else {
113
- // istanbul ignore next
114
- if (dataTypeNodeId.value != 0) {
115
- warningLog("Warning: Cannot find dataType", dataTypeNodeId.toString());
112
+ const isType = types.indexOf(node.nodeClass);
113
+ const isInstance = instances.indexOf(node.nodeClass);
114
+ if (isType !== -1) {
115
+ nbTypes++;
116
+ const superTypes = node.findReferencesAsObject("HasSubtype", false);
117
+ if (superTypes.length === 0) {
118
+ continue;
119
+ }
120
+ if (superTypes.length !== 1) {
121
+ continue;
122
+ }
123
+ const superType = superTypes[0];
124
+ if (superType.nodeId.namespace === 0) {
125
+ continue;
126
+ }
127
+ const requiredModel = superType.nodeId.namespace;
128
+ consider(requiredModel);
129
+ } else if (isInstance !== -1) {
130
+ if (node.nodeClass === NodeClass.Variable || node.nodeClass === NodeClass.VariableType) {
131
+ const dataTypeNodeId = (node as UAVariable | UAVariableType).dataType;
132
+ const dataTypeNode = addressSpace.findDataType(dataTypeNodeId)!;
133
+ if (dataTypeNode) {
134
+ consider(dataTypeNode.nodeId.namespace);
135
+ } else {
136
+ // istanbul ignore next
137
+ if (dataTypeNodeId.value != 0) {
138
+ warningLog("Warning: Cannot find dataType", dataTypeNodeId.toString());
139
+ }
116
140
  }
141
+ const nodeV = node as UAVariableImpl;
142
+ exploreDataValue(nodeV);
117
143
  }
118
- const nodeV = node as UAVariableImpl;
119
- exploreDataValue(nodeV);
144
+
145
+ const typeDefinitions = node.findReferencesAsObject("HasTypeDefinition", true);
146
+ if (typeDefinitions.length === 0) {
147
+ continue;
148
+ }
149
+ if (typeDefinitions.length !== 1) {
150
+ continue;
151
+ }
152
+ const typeDefinition = typeDefinitions[0];
153
+ const requiredModel = typeDefinition.nodeId.namespace;
154
+ consider(requiredModel);
120
155
  }
121
- // visit all references
122
- const references = (<BaseNodeImpl>node).ownReferences();
123
- for (const reference of references) {
124
- // check referenceId
125
- const namespaceIndex = getReferenceType(reference)!.nodeId.namespace;
126
- consider(namespaceIndex);
127
- const namespaceIndex2 = reference.nodeId.namespace;
128
- consider(namespaceIndex2);
156
+ }
157
+
158
+ const result = { requiredNamespaceIndexes: requiredNamespaceIndexes, nbTypes: nbTypes };
159
+ if (cache) {
160
+ cache.set(namespace.index, result);
161
+ }
162
+ return result;
163
+ }
164
+
165
+ export function _recomputeRequiredModelsFromTypes2(
166
+ namespace: INamespace,
167
+ cache?: Map<number, { requiredNamespaceIndexes: number[]; nbTypes: number }>
168
+ ): { requiredNamespaceIndexes: number[] } {
169
+ const addressSpace = namespace.addressSpace;
170
+
171
+ const { requiredNamespaceIndexes } = _recomputeRequiredModelsFromTypes(namespace, cache);
172
+
173
+ const set = new Set<number>(requiredNamespaceIndexes);
174
+ const pass2: number[] = [];
175
+ for (const r of requiredNamespaceIndexes) {
176
+ if (r === 0) {
177
+ pass2.push(0);
178
+ continue;
179
+ }
180
+ const namespaces = _recomputeRequiredModelsFromTypes(addressSpace.getNamespace(r), cache);
181
+ for (const nIndex of namespaces.requiredNamespaceIndexes) {
182
+ if (!set.has(nIndex)) {
183
+ set.add(nIndex);
184
+ pass2.push(nIndex);
185
+ }
129
186
  }
187
+ pass2.push(r);
130
188
  }
189
+
190
+ return { requiredNamespaceIndexes: pass2 };
131
191
  }
132
192
 
133
- export function hasHigherPriorityThan(namespaceIndex1: number, namespaceIndex2: number, priorityTable: number[]) {
134
- const order1 = priorityTable[namespaceIndex1];
135
- const order2 = priorityTable[namespaceIndex2];
136
- return order1 > order2;
193
+ export function _getCompleteRequiredModelsFromValuesAndReferences(
194
+ namespace: INamespace,
195
+ priorityList: number[],
196
+ cache?: Map<number, { requiredNamespaceIndexes: number[]; nbTypes: number }>
197
+ ): number[] {
198
+
199
+ const namespace_ = namespace as NamespacePrivate;
200
+
201
+ const thisPriority = priorityList[namespace.index];
202
+
203
+ const requiredNamespaceIndexes = _recomputeRequiredModelsFromTypes2(namespace, cache).requiredNamespaceIndexes;
204
+ const requiredModelsSet: Set<number> = new Set<number>([... requiredNamespaceIndexes]);
205
+
206
+ const consider = (requiredModel: number) => {
207
+ if (requiredModel !== namespace.index && !requiredModelsSet.has(requiredModel)) {
208
+ requiredModelsSet.add(requiredModel);
209
+ requiredNamespaceIndexes.push(requiredModel);
210
+ }
211
+ }
212
+
213
+ //const maxIndex = Math.max(...requiredNamespaceIndexes);
214
+ for (const node of namespace_.nodeIterator()) {
215
+ const references = (<BaseNodeImpl>node).allReferences();
216
+ for (const reference of references) {
217
+ // if (reference.isForward) continue;
218
+ // only look at backward reference
219
+ // check referenceId
220
+ const namespaceIndexOfReferenceType = getReferenceType(reference)!.nodeId.namespace;
221
+ if (namespaceIndexOfReferenceType !== 0 && namespaceIndexOfReferenceType !== namespace.index) {
222
+ const refPriority = priorityList[namespaceIndexOfReferenceType];
223
+ if (refPriority <= thisPriority) {
224
+ consider(namespaceIndexOfReferenceType);
225
+ }
226
+ }
227
+ const namespaceIndexOfTargetNode = reference.nodeId.namespace;
228
+ if (namespaceIndexOfTargetNode !== 0 && namespaceIndexOfTargetNode !== namespace.index) {
229
+ const refPriority = priorityList[namespaceIndexOfTargetNode];
230
+ if (refPriority <= thisPriority) {
231
+ consider(namespaceIndexOfTargetNode);
232
+ }
233
+ }
234
+ }
235
+ }
236
+ return requiredNamespaceIndexes;
137
237
  }
138
238
 
139
239
  /**
@@ -150,58 +250,99 @@ export function hasHigherPriorityThan(namespaceIndex1: number, namespaceIndex2:
150
250
  * ---
151
251
  * ua, own , di , kitchen , own2, adi => 0 , 2, 3, 5, 1
152
252
  */
153
- export function constructNamespacePriorityTable(namespace: INamespace): number[] {
154
- // Namespace 0 will always be 0
155
- // Namespaces with no requiredModel will be considered as instance namespaces and will added at the end
156
- // in the same order as they appear,
157
- // Namespace with requiredModels are considered to be companion specification, so already loaded in the correct order
158
-
159
- const addressSpace = namespace.addressSpace;
253
+ export function constructNamespacePriorityTable(addressSpace: IAddressSpace): { loadingOrder: number[]; priorityTable: number[] } {
254
+ // - Namespace 0 will always be 0
255
+ // - Namespace with requiredModels are considered to be companion specification,
256
+ // so RequireModel will be used to determine the order
257
+ // - Namespaces with no requiredModel are more complicated:
258
+ //
259
+ // we study ObjectType,ReferenceType, DataType and VariableType
260
+ // to find strong dependencies between namespace.
261
+ //
262
+ // if the namespace doesn't define ObjectType,ReferenceType, DataType and VariableType
263
+ // it will be considered as instance namespaces and will added at the end
264
+ // in the same order as they appear,
160
265
  const namespaces = addressSpace.getNamespaceArray();
161
266
 
162
- const namespaceWithReq = namespaces.filter((n) => n.getRequiredModels() !== undefined && n.index !== 0);
163
- const namespaceWithoutReq = namespaces.filter((n) => n.getRequiredModels() === undefined && n.index !== 0);
267
+ const loadingOrder: number[] = [0];
164
268
 
165
- const priorityList: number[] = [0];
166
- let counter = 1;
167
- for (let i = 0; i < namespaceWithReq.length; i++) {
168
- priorityList[namespaceWithReq[i].index] = counter++;
169
- }
170
- for (let i = 0; i < namespaceWithoutReq.length; i++) {
171
- priorityList[namespaceWithoutReq[i].index] = counter++;
269
+ const map = new Map<number, { nbTypes: number; requiredNamespaceIndexes: number[]; namespace: INamespace }>();
270
+ for (let i = 0; i < namespaces.length; i++) {
271
+ const { nbTypes, requiredNamespaceIndexes } = _recomputeRequiredModelsFromTypes(namespaces[i], map);
272
+ map.set(namespaces[i].index, { nbTypes, requiredNamespaceIndexes, namespace: namespaces[i] });
172
273
  }
173
- return priorityList;
174
- }
175
- const doDebug = false;
176
- export function constructNamespaceDependency(namespace: INamespace, priorityTable?: number[]): INamespace[] {
177
- const addressSpace = namespace.addressSpace;
178
274
 
179
- priorityTable = priorityTable || constructNamespacePriorityTable(namespace);
275
+ const visited = new Set<number>();
276
+ visited.add(0);
180
277
 
181
- const dependency: INamespace[] = [];
182
- const depMap = new Set<number>();
278
+ const h = (n: INamespace) => {
279
+ if (visited.has(n.index)) {
280
+ return;
281
+ }
282
+ visited.add(n.index);
283
+ const data = map.get(n.index);
284
+ if (!data) return;
285
+ const { requiredNamespaceIndexes } = data;
286
+ for (const r of requiredNamespaceIndexes || []) {
287
+ h(namespaces[r]);
288
+ }
289
+ loadingOrder.push(n.index);
290
+ };
183
291
 
184
- dependency.push(addressSpace.getDefaultNamespace());
185
- depMap.add(0);
292
+ for (let i = 0; i < namespaces.length; i++) {
293
+ const { nbTypes } = map.get(i)!;
294
+ if (nbTypes) {
295
+ h(namespaces[i]);
296
+ }
297
+ }
298
+ for (let i = 0; i < namespaces.length; i++) {
299
+ const { nbTypes } = map.get(i)!;
300
+ if (!nbTypes) {
301
+ h(namespaces[i]);
302
+ }
303
+ }
186
304
 
187
- if (namespace !== addressSpace.getDefaultNamespace()) {
188
- dependency.push(namespace);
189
- depMap.add(namespace.index);
305
+ const priorityTable: number[] = [];
306
+ for (let i = 0; i < loadingOrder.length; i++) {
307
+ const namespaceIndex = loadingOrder[i];
308
+ assert(namespaceIndex !== -1);
309
+ priorityTable[namespaceIndex] = i;
190
310
  }
191
- const _visitedDataType = new Set<string>();
192
311
 
193
- _constructNamespaceDependency(namespace, dependency, depMap, _visitedDataType, priorityTable);
312
+ return { loadingOrder, priorityTable };
313
+ }
194
314
 
195
- // istanbul ignore next
196
- doDebug && debugLog("namespace : ", namespace.index, namespace.namespaceUri);
197
- // istanbul ignore next
198
- doDebug && debugLog(" ", dependency.map((d) => d.index + " " + d.namespaceUri).join("\n "));
315
+ const doDebug = true;
316
+ export function constructNamespaceDependency(namespace: INamespace, priorityTable?: number[]): INamespace[] {
317
+ const addressSpace = namespace.addressSpace;
318
+ priorityTable = priorityTable || constructNamespacePriorityTable(addressSpace).priorityTable;
319
+ const requiredNamespaceIndexes = _getCompleteRequiredModelsFromValuesAndReferences(namespace, priorityTable);
320
+ return [...requiredNamespaceIndexes.map((r) => addressSpace.getNamespace(r)), namespace];
321
+ }
199
322
 
200
- const sorted = dependency.sort((a, b) => (priorityTable![a.index] < priorityTable![b.index] ? -1 : 1));
201
- // istanbul ignore next
202
- doDebug && debugLog("sorted:");
203
- // istanbul ignore next
204
- doDebug && debugLog(" ", sorted.map((d) => d.index + " " + d.namespaceUri).join("\n "));
323
+ /**
324
+ * @private
325
+ */
326
+ export function _constructNamespaceTranslationTable(dependency: INamespace[], exportedNamespace: INamespace): ITranslationTable {
327
+ if (!dependency || dependency.length === 0) {
328
+ return { 0: 0 };
329
+ // throw new Error("Cannot constructNamespaceTranslationTable on empty dependency");
330
+ }
331
+ const translationTable: ITranslationTable = {};
332
+ assert(dependency[0].namespaceUri === "http://opcfoundation.org/UA/");
205
333
 
206
- return sorted;
334
+ let counter = 0;
335
+ translationTable[dependency[0].index] = counter++;
336
+ //
337
+ if (exportedNamespace) {
338
+ translationTable[exportedNamespace.index] = counter++;
339
+ }
340
+ for (let i = 1; i < dependency.length; i++) {
341
+ const dep = dependency[i];
342
+ if (exportedNamespace && exportedNamespace === dep) {
343
+ continue;
344
+ }
345
+ translationTable[dep.index] = counter++;
346
+ }
347
+ return translationTable;
207
348
  }
@@ -18,7 +18,7 @@ import {
18
18
  QualifiedName
19
19
  } from "node-opcua-data-model";
20
20
  import { ExpandedNodeId, NodeId, NodeIdType, resolveNodeId } from "node-opcua-nodeid";
21
- import * as utils from "node-opcua-utils";
21
+ import { lowerFirstLetter, isNullOrUndefined } from "node-opcua-utils";
22
22
  import { Variant, VariantArrayType, DataType } from "node-opcua-variant";
23
23
  import {
24
24
  IAddressSpace,
@@ -53,9 +53,9 @@ import { UAViewImpl } from "../ua_view_impl";
53
53
  import { DefinitionMap2, TypeInfo } from "../../source/loader/make_xml_extension_object_parser";
54
54
  import { makeDefinitionMap } from "../../source/loader/decode_xml_extension_object";
55
55
  import {
56
+ _constructNamespaceTranslationTable,
56
57
  constructNamespaceDependency,
57
- constructNamespacePriorityTable,
58
- hasHigherPriorityThan
58
+ constructNamespacePriorityTable
59
59
  } from "./construct_namespace_dependency";
60
60
 
61
61
  // tslint:disable:no-var-requires
@@ -105,6 +105,12 @@ function b(xw: XmlWriter, browseName: QualifiedName): string {
105
105
  return translateBrowseName(xw, browseName).toString().replace("ns=0;", "");
106
106
  }
107
107
 
108
+ function hasHigherPriorityThan(namespaceIndex1: number, namespaceIndex2: number, priorityTable: number[]) {
109
+ const order1 = priorityTable[namespaceIndex1];
110
+ const order2 = priorityTable[namespaceIndex2];
111
+ return order1 > order2;
112
+ }
113
+
108
114
  function _hasHigherPriorityThan(xw: XmlWriter, namespaceIndex1: number, namespaceIndex2: number) {
109
115
  assert(xw.priorityTable, "expecting a priorityTable");
110
116
  assert(namespaceIndex1 < xw.priorityTable.length);
@@ -128,7 +134,6 @@ function _dumpReferences(xw: XmlWriter, node: BaseNode) {
128
134
 
129
135
  function referenceToKeep(reference: UAReference): boolean {
130
136
  const referenceType = (reference as ReferenceImpl)._referenceType!;
131
-
132
137
  const targetedNamespaceIndex = reference.nodeId.namespace;
133
138
  if (_hasHigherPriorityThan(xw, targetedNamespaceIndex, node.nodeId.namespace)) {
134
139
  // this reference has nothing to do here ! drop it
@@ -165,8 +170,8 @@ function _dumpReferences(xw: XmlWriter, node: BaseNode) {
165
170
  }
166
171
  return false;
167
172
  }
168
-
169
- const references = node.allReferences().filter(referenceToKeep);
173
+ const allReferences = node.allReferences();
174
+ const references = allReferences.filter(referenceToKeep);
170
175
 
171
176
  for (const reference of references.sort(sortByNodeId)) {
172
177
  if (getReferenceType(reference).browseName.toString() === "HasSubtype" && reference.isForward) {
@@ -329,7 +334,7 @@ function _dumpVariantInnerExtensionObject(
329
334
  const dataTypeNodeId = field.dataType;
330
335
 
331
336
  const fieldName = field.name!;
332
- const lowerFieldName = utils.lowerFirstLetter(fieldName);
337
+ const lowerFieldName = lowerFirstLetter(fieldName);
333
338
  const v = (value as unknown as Record<string, unknown>)[lowerFieldName];
334
339
  if (v !== null && v !== undefined) {
335
340
  if (
@@ -535,6 +540,10 @@ function _dumpVariantExtensionObjectValue2(xw: XmlWriter, addressSpace: IAddress
535
540
  const dataTypeNodeId = value.schema.dataTypeNodeId;
536
541
  const definitionMap = makeDefinitionMap(addressSpace);
537
542
  const dataTypeNode = addressSpace.findDataType(dataTypeNodeId)!;
543
+ if (!dataTypeNode) {
544
+ warningLog("_dumpVariantExtensionObjectValue2: Cannot find dataType for ", dataTypeNodeId.toString());
545
+ return;
546
+ }
538
547
  _dumpVariantExtensionObjectValue(xw, dataTypeNode.nodeId, definitionMap, value);
539
548
  }
540
549
 
@@ -845,7 +854,7 @@ function _dumpEnumDefinition(xw: XmlWriter, enumDefinition: EnumDefinition) {
845
854
  for (const defItem of enumDefinition.fields!) {
846
855
  xw.startElement("Field");
847
856
  xw.writeAttribute("Name", defItem.name as string);
848
- if (!utils.isNullOrUndefined(defItem.value)) {
857
+ if (!isNullOrUndefined(defItem.value)) {
849
858
  xw.writeAttribute("Value", coerceInt64ToInt32(defItem.value));
850
859
  }
851
860
  _dumpDescription(xw, defItem);
@@ -1155,7 +1164,7 @@ function dumpUAObjectType(xw: XmlWriter, node: UAObjectTypeImpl) {
1155
1164
  xw.writeComment("ObjectType - " + b(xw, node.browseName) + " {{{{ ");
1156
1165
  _markAsVisited(xw, node);
1157
1166
 
1158
- // dump SubtypeOf and HasTypeDefinition
1167
+ // dump SubtypeOf and HasTypeDefinition node if part of the same namespace
1159
1168
  dumpReferencedNodes(xw, node, false);
1160
1169
 
1161
1170
  xw.startElement("UAObjectType");
@@ -1268,25 +1277,6 @@ function writeAliases(xw: XmlWriter, aliases: Record<string, NodeIdString>) {
1268
1277
  xw.endElement();
1269
1278
  }
1270
1279
 
1271
- function constructNamespaceTranslationTable(dependency: INamespace[], exportedNamespace: INamespace): ITranslationTable {
1272
- const translationTable: ITranslationTable = {};
1273
- assert(dependency[0].namespaceUri === "http://opcfoundation.org/UA/");
1274
-
1275
- let counter = 0;
1276
- translationTable[dependency[0].index] = counter++;
1277
- //
1278
- if (exportedNamespace) {
1279
- translationTable[exportedNamespace.index] = counter++;
1280
- }
1281
- for (let i = 1; i < dependency.length; i++) {
1282
- const dep = dependency[i];
1283
- if (exportedNamespace && exportedNamespace === dep) {
1284
- continue;
1285
- }
1286
- translationTable[dep.index] = counter++;
1287
- }
1288
- return translationTable;
1289
- }
1290
1280
  function dumpReferenceType(xw: XmlWriter, referenceType: UAReferenceType) {
1291
1281
  _markAsVisited(xw, referenceType);
1292
1282
 
@@ -1382,9 +1372,10 @@ NamespaceImpl.prototype.toNodeset2XML = function (this: NamespaceImpl) {
1382
1372
 
1383
1373
  const xw: XmlWriter = new XMLWriter(true);
1384
1374
 
1385
- xw.priorityTable = constructNamespacePriorityTable(this);
1375
+ xw.priorityTable = constructNamespacePriorityTable(this.addressSpace).priorityTable;
1376
+
1386
1377
  const dependency = constructNamespaceDependency(this, xw.priorityTable);
1387
- const translationTable = constructNamespaceTranslationTable(dependency, this);
1378
+ const translationTable = _constructNamespaceTranslationTable(dependency, this);
1388
1379
  xw.translationTable = translationTable;
1389
1380
 
1390
1381
  xw.startDocument({ encoding: "utf-8", version: "1.0" });
@@ -6,7 +6,7 @@ import chalk from "chalk";
6
6
  import { AddReferenceOpts, UAReference, BaseNode, UAReferenceType } from "node-opcua-address-space-base";
7
7
  import { assert } from "node-opcua-assert";
8
8
  import { coerceNodeId, NodeId, NodeIdLike, sameNodeId } from "node-opcua-nodeid";
9
- import * as utils from "node-opcua-utils";
9
+ import { isNullOrUndefined } from "node-opcua-utils";
10
10
 
11
11
  export function isNodeIdString(str: string): boolean {
12
12
  assert(typeof str === "string");
@@ -17,7 +17,7 @@ function is_valid_reference(ref: UAReference): boolean {
17
17
  const hasRequestedProperties =
18
18
  Object.prototype.hasOwnProperty.call(ref, "referenceType") &&
19
19
  Object.prototype.hasOwnProperty.call(ref, "nodeId") &&
20
- !utils.isNullOrUndefined(ref.isForward);
20
+ !isNullOrUndefined(ref.isForward);
21
21
 
22
22
  if (!hasRequestedProperties) {
23
23
  return false;
@@ -21,16 +21,16 @@ import {
21
21
  import { DataType } from "node-opcua-variant";
22
22
  import { UAObject, ISessionContext, UADataType, UAVariable, BaseNode } from "node-opcua-address-space-base";
23
23
  import { DataTypeIds } from "node-opcua-constants";
24
+ import { Int64, coerceInt32, coerceInt64, coerceInt64toInt32 } from "node-opcua-basic-types";
24
25
 
25
26
  import { SessionContext } from "../source/session_context";
26
27
  import { ExtensionObjectConstructorFuncWithSchema } from "../source/interfaces/extension_object_constructor";
27
28
  import { BaseNodeImpl, InternalBaseNodeOptions } from "./base_node_impl";
28
29
  import { BaseNode_References_toString, BaseNode_toString, ToStringBuilder, ToStringOption } from "./base_node_private";
29
- import * as tools from "./tool_isSubtypeOf";
30
+ import { construct_isSubtypeOf } from "./tool_isSubtypeOf";
30
31
  import { get_subtypeOf } from "./tool_isSubtypeOf";
31
32
  import { get_subtypeOfObj } from "./tool_isSubtypeOf";
32
33
  import { BaseNode_getCache } from "./base_node_private";
33
- import { Int64, coerceInt32, coerceInt64, coerceInt64toInt32 } from "node-opcua-basic-types";
34
34
 
35
35
  export interface UADataTypeImpl {
36
36
  _extensionObjectConstructor: ExtensionObjectConstructorFuncWithSchema;
@@ -76,8 +76,8 @@ export class UADataTypeImpl extends BaseNodeImpl implements UADataType {
76
76
  }
77
77
 
78
78
  /** @deprecated */
79
- public isSupertypeOf = tools.construct_isSubtypeOf<UADataType>(UADataTypeImpl);
80
- public isSubtypeOf = tools.construct_isSubtypeOf<UADataType>(UADataTypeImpl);
79
+ public isSupertypeOf = construct_isSubtypeOf<UADataType>(UADataTypeImpl);
80
+ public isSubtypeOf = construct_isSubtypeOf<UADataType>(UADataTypeImpl);
81
81
 
82
82
  public readonly isAbstract: boolean;
83
83
 
@@ -370,24 +370,24 @@ export function DataType_toString(this: UADataTypeImpl, options: ToStringOption)
370
370
 
371
371
  options.add(
372
372
  options.padding +
373
- chalk.yellow(" binaryEncodingNodeId: ") +
374
- (this.binaryEncodingNodeId ? this.binaryEncodingNodeId.toString() : "<none>")
373
+ chalk.yellow(" binaryEncodingNodeId: ") +
374
+ (this.binaryEncodingNodeId ? this.binaryEncodingNodeId.toString() : "<none>")
375
375
  );
376
376
  options.add(
377
377
  options.padding +
378
- chalk.yellow(" xmlEncodingNodeId : ") +
379
- (this.xmlEncodingNodeId ? this.xmlEncodingNodeId.toString() : "<none>")
378
+ chalk.yellow(" xmlEncodingNodeId : ") +
379
+ (this.xmlEncodingNodeId ? this.xmlEncodingNodeId.toString() : "<none>")
380
380
  );
381
381
  options.add(
382
382
  options.padding +
383
- chalk.yellow(" jsonEncodingNodeId : ") +
384
- (this.jsonEncodingNodeId ? this.jsonEncodingNodeId.toString() : "<none>")
383
+ chalk.yellow(" jsonEncodingNodeId : ") +
384
+ (this.jsonEncodingNodeId ? this.jsonEncodingNodeId.toString() : "<none>")
385
385
  );
386
386
  if (this.subtypeOfObj) {
387
387
  options.add(
388
388
  options.padding +
389
- chalk.yellow(" subtypeOfObj : ") +
390
- (this.subtypeOfObj ? this.subtypeOfObj.browseName.toString() : "")
389
+ chalk.yellow(" subtypeOfObj : ") +
390
+ (this.subtypeOfObj ? this.subtypeOfObj.browseName.toString() : "")
391
391
  );
392
392
  }
393
393
  // references
@@ -396,7 +396,6 @@ export function DataType_toString(this: UADataTypeImpl, options: ToStringOption)
396
396
  dataTypeDefinition_toString.call(this, options);
397
397
  }
398
398
 
399
-
400
399
  const defaultEnumValue: Int64 = coerceInt64(-1);
401
400
 
402
401
  function makeEnumDefinition(definitionFields: EnumFieldOptions[]) {
@@ -424,8 +423,8 @@ function makeStructureDefinition(
424
423
  const structureType = isUnion
425
424
  ? StructureType.Union
426
425
  : hasOptionalFields
427
- ? StructureType.StructureWithOptionalFields
428
- : StructureType.Structure;
426
+ ? StructureType.StructureWithOptionalFields
427
+ : StructureType.Structure;
429
428
 
430
429
  const sd = new StructureDefinition({
431
430
  baseDataType,
@@ -7,7 +7,7 @@ import { AttributeIds } from "node-opcua-data-model";
7
7
  import { DataValue, DataValueLike } from "node-opcua-data-value";
8
8
  import { NodeId } from "node-opcua-nodeid";
9
9
  import { StatusCodes } from "node-opcua-status-code";
10
- import * as utils from "node-opcua-utils";
10
+ import { isNullOrUndefined } from "node-opcua-utils";
11
11
  import { DataType } from "node-opcua-variant";
12
12
  import {
13
13
  AddObjectOptions,
@@ -21,8 +21,8 @@ import {
21
21
  import { SessionContext } from "../source/session_context";
22
22
  import { BaseNodeImpl } from "./base_node_impl";
23
23
  import { ToStringBuilder, UAObjectType_toString } from "./base_node_private";
24
- import { get_subtypeOf, get_subtypeOfObj } from "./tool_isSubtypeOf";
25
- import * as tools from "./tool_isSubtypeOf";
24
+ import { construct_isSubtypeOf, get_subtypeOf, get_subtypeOfObj } from "./tool_isSubtypeOf";
25
+ import { } from "./tool_isSubtypeOf";
26
26
  import {
27
27
  assertUnusedChildBrowseName,
28
28
  topMostParentIsObjectTypeOrVariableType
@@ -49,13 +49,13 @@ export class UAObjectTypeImpl extends BaseNodeImpl implements UAObjectType {
49
49
  }
50
50
 
51
51
 
52
- public isSubtypeOf = tools.construct_isSubtypeOf<UAObjectType>(UAObjectTypeImpl);
52
+ public isSubtypeOf = construct_isSubtypeOf<UAObjectType>(UAObjectTypeImpl);
53
53
  /** @deprecated - use isSubtypeOf instead */
54
- public isSupertypeOf = tools.construct_isSubtypeOf<UAObjectType>(UAObjectTypeImpl);
54
+ public isSupertypeOf = construct_isSubtypeOf<UAObjectType>(UAObjectTypeImpl);
55
55
 
56
56
  constructor(options: any) {
57
57
  super(options);
58
- this.isAbstract = utils.isNullOrUndefined(options.isAbstract) ? false : options.isAbstract;
58
+ this.isAbstract = isNullOrUndefined(options.isAbstract) ? false : options.isAbstract;
59
59
  }
60
60
 
61
61
  public readAttribute(context: ISessionContext, attributeId: AttributeIds): DataValue {