-
-
Notifications
You must be signed in to change notification settings - Fork 478
/
address_space_change_event_tools.ts
188 lines (151 loc) · 6.73 KB
/
address_space_change_event_tools.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
* @module node-opcua-address-space
*/
import * as chalk from "chalk";
import { assert } from "node-opcua-assert";
import { ModelChangeStructureDataType } from "node-opcua-common";
import { NodeClass } from "node-opcua-data-model";
import { BrowseDirection } from "node-opcua-data-model";
import { Enum, EnumItem } from "node-opcua-enum";
import { NodeId } from "node-opcua-nodeid";
import { UAReference } from "../source";
import { AddressSpacePrivate } from "./address_space_private";
import { BaseNode } from "./base_node";
const verbFlags = new Enum({
// NodeAdded 0 Indicates the affected Node has been added.
NodeAdded: 0x01,
// NodeDeleted 1 Indicates the affected Node has been deleted.
NodeDeleted: 0x02,
// ReferenceAdded 2 Indicates a Reference has been added. The affected Node may
ReferenceAdded: 0x04,
// be either a SourceNode or TargetNode. Note that an added
// bidirectional Reference is reflected by two ChangeStructures.
// ReferenceDeleted 3 Indicates a Reference has been deleted. The affected Node may
// be either a SourceNode or TargetNode. Note that a deleted
// bidirectional Reference is reflected by two ChangeStructures.
ReferenceDeleted: 0x08,
// DataTypeChanged 4 This verb may be used only for affected Nodes that are
// Variables or VariableTypes. It indicates that the DataType
// Attribute has changed.
DataTypeChanged: 0x10
});
function makeVerb(verbs: any): number {
const e: EnumItem = verbFlags.get(verbs)!;
assert(e !== null);
return e.value;
}
export function _handle_add_reference_change_event(
node1: BaseNode,
node2id: NodeId
) {
const addressSpace = node1.addressSpace as AddressSpacePrivate;
const node2 = addressSpace.findNode(node2id)! as BaseNode;
if (node1.nodeVersion || (node2 && node2.nodeVersion)) {
// a event has to be send
addressSpace.modelChangeTransaction(() => {
function _getTypeDef(node: BaseNode) {
if (node.nodeClass === NodeClass.Object || node.nodeClass === NodeClass.Variable) {
return node.typeDefinitionObj.nodeId;
}
return null;
}
let modelChangeTgt = new ModelChangeStructureDataType({
affected: node1.nodeId,
affectedType: _getTypeDef(node1),
verb: makeVerb("ReferenceAdded")
});
addressSpace._collectModelChange(null, modelChangeTgt);
modelChangeTgt = new ModelChangeStructureDataType({
affected: node2.nodeId,
affectedType: _getTypeDef(node2),
verb: makeVerb("ReferenceAdded")
});
addressSpace._collectModelChange(null, modelChangeTgt);
});
}
}
try {
(ModelChangeStructureDataType as any).prototype.toString = function(options: any): string {
if (!options) {
return "";
}
const addressSpace = options.addressSpace;
function n(nodeId: NodeId | null) {
if (!nodeId || nodeId.isEmpty()) {
return "";
}
const node = addressSpace.findNode(nodeId)!;
return "\"" + nodeId.toString() +
"\"" + chalk.yellow(" /* " + (node ? node.browseName.toString() : "???") + " */");
}
let str = "{ verb:" + verbFlags.get(this.verb)!.key + ",";
str += " affected: " + n(this.affected) + ",";
str += " type: " + n(this.affectedType) + " }";
return str;
};
} catch (err) {
//
}
export function _handle_model_change_event(node: BaseNode) {
const addressSpace = node.addressSpace;
//
const parent = node.parent!;
if (parent && (parent as any).nodeVersion) {
addressSpace.modelChangeTransaction(() => {
let typeDefinitionNodeId = null;
if (node.nodeClass === NodeClass.Object || node.nodeClass === NodeClass.Variable) {
typeDefinitionNodeId = node.typeDefinitionObj.nodeId;
}
const modelChange1 = new ModelChangeStructureDataType({
affected: node.nodeId,
affectedType: typeDefinitionNodeId,
verb: makeVerb("NodeAdded")
});
addressSpace._collectModelChange(null, modelChange1);
const modelChangeSrc = new ModelChangeStructureDataType({
affected: parent.nodeId,
affectedType: null,
verb: makeVerb("ReferenceAdded")
});
addressSpace._collectModelChange(null, modelChangeSrc);
// bidirectional
if (node.nodeVersion) {
const modelChangeTgt = new ModelChangeStructureDataType({
affected: node.nodeId,
affectedType: typeDefinitionNodeId,
verb: makeVerb("ReferenceAdded")
});
addressSpace._collectModelChange(null, modelChangeTgt);
}
});
}
}
export function _handle_delete_node_model_change_event(node: BaseNode) {
const addressSpace = node.addressSpace;
// get backward references
const references = node.findReferencesEx("HierarchicalReferences", BrowseDirection.Inverse)!;
const parentNodes = references.map((r: UAReference) => {
return addressSpace.findNode(r.nodeId)! as BaseNode;
});
const versionableNodes = parentNodes.filter((n: BaseNode) => !!n.nodeVersion);
if (versionableNodes.length >= 1 || !!node.nodeVersion) {
addressSpace.modelChangeTransaction(() => {
// ...
for (const r of references) {
const target = addressSpace.findNode(r.nodeId)!;
const modelChangeSrc_l = new ModelChangeStructureDataType({
affected: target.nodeId,
affectedType: null,
verb: makeVerb("ReferenceDeleted")
});
addressSpace._collectModelChange(null, modelChangeSrc_l);
}
const modelChangeSrc = new ModelChangeStructureDataType({
affected: node.nodeId,
affectedType: node.typeDefinition,
verb: makeVerb("NodeDeleted")
});
addressSpace._collectModelChange(null, modelChangeSrc);
});
}
}