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.
- package/dist/source/loader/generateAddressSpaceRaw.js +8 -4
- package/dist/source/loader/generateAddressSpaceRaw.js.map +1 -1
- package/dist/source/loader/load_nodeset2.js +2 -2
- package/dist/source/loader/load_nodeset2.js.map +1 -1
- package/dist/source/pseudo_session.js +12 -26
- package/dist/source/pseudo_session.js.map +1 -1
- package/dist/src/address_space.js +4 -27
- package/dist/src/address_space.js.map +1 -1
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js +2 -25
- package/dist/src/alarms_and_conditions/ua_off_normal_alarm_impl.js.map +1 -1
- package/dist/src/base_node_impl.js +2 -25
- package/dist/src/base_node_impl.js.map +1 -1
- package/dist/src/namespace_impl.js +3 -26
- package/dist/src/namespace_impl.js.map +1 -1
- package/dist/src/nodeset_tools/construct_namespace_dependency.d.ts +27 -3
- package/dist/src/nodeset_tools/construct_namespace_dependency.js +210 -81
- package/dist/src/nodeset_tools/construct_namespace_dependency.js.map +1 -1
- package/dist/src/nodeset_tools/nodeset_to_xml.js +18 -49
- package/dist/src/nodeset_tools/nodeset_to_xml.js.map +1 -1
- package/dist/src/reference_impl.js +2 -25
- package/dist/src/reference_impl.js.map +1 -1
- package/dist/src/ua_data_type_impl.d.ts +2 -3
- package/dist/src/ua_data_type_impl.js +6 -29
- package/dist/src/ua_data_type_impl.js.map +1 -1
- package/dist/src/ua_object_type_impl.d.ts +2 -3
- package/dist/src/ua_object_type_impl.js +4 -28
- package/dist/src/ua_object_type_impl.js.map +1 -1
- package/dist/src/ua_reference_type_impl.d.ts +2 -3
- package/dist/src/ua_reference_type_impl.js +6 -29
- package/dist/src/ua_reference_type_impl.js.map +1 -1
- package/dist/src/ua_variable_impl.js +3 -26
- package/dist/src/ua_variable_impl.js.map +1 -1
- package/dist/src/ua_variable_type_impl.d.ts +2 -3
- package/dist/src/ua_variable_type_impl.js +5 -28
- package/dist/src/ua_variable_type_impl.js.map +1 -1
- package/dist/tsconfig_common.tsbuildinfo +1 -1
- package/distHelpers/get_address_space_fixture.js +16 -36
- package/distHelpers/get_address_space_fixture.js.map +1 -1
- package/distNodeJS/generate_address_space.js +5 -25
- package/distNodeJS/generate_address_space.js.map +1 -1
- package/package.json +40 -40
- package/source/loader/generateAddressSpaceRaw.ts +10 -4
- package/source/loader/load_nodeset2.ts +2 -2
- package/source/pseudo_session.ts +8 -2
- package/source_nodejs/generate_address_space.ts +1 -1
- package/src/address_space.ts +2 -2
- package/src/alarms_and_conditions/ua_off_normal_alarm_impl.ts +2 -4
- package/src/base_node_impl.ts +2 -2
- package/src/namespace_impl.ts +5 -7
- package/src/nodeset_tools/construct_namespace_dependency.ts +232 -91
- package/src/nodeset_tools/nodeset_to_xml.ts +21 -30
- package/src/reference_impl.ts +2 -2
- package/src/ua_data_type_impl.ts +14 -15
- package/src/ua_object_type_impl.ts +6 -6
- package/src/ua_reference_type_impl.ts +4 -4
- package/src/ua_variable_impl.ts +4 -6
- 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
|
-
|
|
17
|
+
// eslint-disable-next-line max-statements, complexity
|
|
18
|
+
export function _recomputeRequiredModelsFromTypes(
|
|
17
19
|
namespace: INamespace,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
34
|
-
if (
|
|
35
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
119
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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(
|
|
154
|
-
// Namespace 0 will always be 0
|
|
155
|
-
//
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
|
|
159
|
-
|
|
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
|
|
163
|
-
const namespaceWithoutReq = namespaces.filter((n) => n.getRequiredModels() === undefined && n.index !== 0);
|
|
267
|
+
const loadingOrder: number[] = [0];
|
|
164
268
|
|
|
165
|
-
const
|
|
166
|
-
let
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
|
|
275
|
+
const visited = new Set<number>();
|
|
276
|
+
visited.add(0);
|
|
180
277
|
|
|
181
|
-
const
|
|
182
|
-
|
|
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
|
-
|
|
185
|
-
|
|
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
|
-
|
|
188
|
-
|
|
189
|
-
|
|
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
|
-
|
|
312
|
+
return { loadingOrder, priorityTable };
|
|
313
|
+
}
|
|
194
314
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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 (!
|
|
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 =
|
|
1378
|
+
const translationTable = _constructNamespaceTranslationTable(dependency, this);
|
|
1388
1379
|
xw.translationTable = translationTable;
|
|
1389
1380
|
|
|
1390
1381
|
xw.startDocument({ encoding: "utf-8", version: "1.0" });
|
package/src/reference_impl.ts
CHANGED
|
@@ -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
|
|
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
|
-
!
|
|
20
|
+
!isNullOrUndefined(ref.isForward);
|
|
21
21
|
|
|
22
22
|
if (!hasRequestedProperties) {
|
|
23
23
|
return false;
|
package/src/ua_data_type_impl.ts
CHANGED
|
@@ -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
|
|
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 =
|
|
80
|
-
public isSubtypeOf =
|
|
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
|
-
|
|
374
|
-
|
|
373
|
+
chalk.yellow(" binaryEncodingNodeId: ") +
|
|
374
|
+
(this.binaryEncodingNodeId ? this.binaryEncodingNodeId.toString() : "<none>")
|
|
375
375
|
);
|
|
376
376
|
options.add(
|
|
377
377
|
options.padding +
|
|
378
|
-
|
|
379
|
-
|
|
378
|
+
chalk.yellow(" xmlEncodingNodeId : ") +
|
|
379
|
+
(this.xmlEncodingNodeId ? this.xmlEncodingNodeId.toString() : "<none>")
|
|
380
380
|
);
|
|
381
381
|
options.add(
|
|
382
382
|
options.padding +
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
|
|
390
|
-
|
|
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
|
-
|
|
428
|
-
|
|
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
|
|
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
|
|
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 =
|
|
52
|
+
public isSubtypeOf = construct_isSubtypeOf<UAObjectType>(UAObjectTypeImpl);
|
|
53
53
|
/** @deprecated - use isSubtypeOf instead */
|
|
54
|
-
public isSupertypeOf =
|
|
54
|
+
public isSupertypeOf = construct_isSubtypeOf<UAObjectType>(UAObjectTypeImpl);
|
|
55
55
|
|
|
56
56
|
constructor(options: any) {
|
|
57
57
|
super(options);
|
|
58
|
-
this.isAbstract =
|
|
58
|
+
this.isAbstract = isNullOrUndefined(options.isAbstract) ? false : options.isAbstract;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
public readAttribute(context: ISessionContext, attributeId: AttributeIds): DataValue {
|