opcua_server/node_manager/
node_management.rs1use opcua_types::{
2 AddNodeAttributes, AddNodesItem, AddNodesResult, AddReferencesItem, DeleteNodesItem,
3 DeleteReferencesItem, DiagnosticBits, DiagnosticInfo, ExpandedNodeId, NodeClass, NodeId,
4 QualifiedName, StatusCode,
5};
6
7use super::IntoResult;
8
9#[derive(Debug, Clone)]
10pub struct AddNodeItem {
12 parent_node_id: ExpandedNodeId,
13 reference_type_id: NodeId,
14 requested_new_node_id: NodeId,
15 browse_name: QualifiedName,
16 node_class: NodeClass,
17 node_attributes: AddNodeAttributes,
18 type_definition_id: ExpandedNodeId,
19 diagnostic_bits: DiagnosticBits,
20
21 result_node_id: NodeId,
22 status: StatusCode,
23 diagnostic_info: Option<DiagnosticInfo>,
24}
25
26impl AddNodeItem {
27 pub(crate) fn new(item: AddNodesItem, diagnostic_bits: DiagnosticBits) -> Self {
28 let mut status = StatusCode::BadNotSupported;
29 let attributes = match AddNodeAttributes::from_extension_object(item.node_attributes) {
30 Ok(attr) => attr,
31 Err(e) => {
32 status = e;
33 AddNodeAttributes::None
34 }
35 };
36 if item.requested_new_node_id.server_index != 0 {
37 status = StatusCode::BadNodeIdRejected;
38 }
39
40 Self::validate_attributes(item.node_class, &attributes, &mut status);
41
42 if item.reference_type_id.is_null() {
43 status = StatusCode::BadReferenceTypeIdInvalid;
44 }
45 if item.parent_node_id.is_null() {
46 status = StatusCode::BadParentNodeIdInvalid;
47 }
48
49 match (item.node_class, item.type_definition.is_null()) {
50 (NodeClass::Object | NodeClass::Variable, true) => {
51 status = StatusCode::BadTypeDefinitionInvalid
52 }
53 (NodeClass::Object | NodeClass::Variable, false) => (),
54 (_, false) => status = StatusCode::BadTypeDefinitionInvalid,
55 _ => (),
56 }
57
58 Self {
59 parent_node_id: item.parent_node_id,
60 reference_type_id: item.reference_type_id,
61 requested_new_node_id: item.requested_new_node_id.node_id,
62 browse_name: item.browse_name,
63 node_class: item.node_class,
64 node_attributes: attributes,
65 type_definition_id: item.type_definition,
66 result_node_id: NodeId::null(),
67 status,
68 diagnostic_info: None,
69 diagnostic_bits,
70 }
71 }
72
73 fn validate_attributes(
74 node_class: NodeClass,
75 attributes: &AddNodeAttributes,
76 status: &mut StatusCode,
77 ) {
78 match (node_class, attributes) {
79 (NodeClass::Object, AddNodeAttributes::Object(_))
80 | (NodeClass::Variable, AddNodeAttributes::Variable(_))
81 | (NodeClass::Method, AddNodeAttributes::Method(_))
82 | (NodeClass::ObjectType, AddNodeAttributes::ObjectType(_))
83 | (NodeClass::VariableType, AddNodeAttributes::VariableType(_))
84 | (NodeClass::ReferenceType, AddNodeAttributes::ReferenceType(_))
85 | (NodeClass::DataType, AddNodeAttributes::DataType(_))
86 | (NodeClass::View, AddNodeAttributes::View(_)) => {}
87 (NodeClass::Unspecified, _) => *status = StatusCode::BadNodeClassInvalid,
88 (_, AddNodeAttributes::None | AddNodeAttributes::Generic(_)) => {}
89 _ => *status = StatusCode::BadNodeAttributesInvalid,
90 }
91 }
92
93 pub fn set_result(&mut self, node_id: NodeId, status: StatusCode) {
95 self.result_node_id = node_id;
96 self.status = status;
97 }
98
99 pub fn parent_node_id(&self) -> &ExpandedNodeId {
101 &self.parent_node_id
102 }
103
104 pub fn reference_type_id(&self) -> &NodeId {
106 &self.reference_type_id
107 }
108
109 pub fn requested_new_node_id(&self) -> &NodeId {
112 &self.requested_new_node_id
113 }
114
115 pub fn browse_name(&self) -> &QualifiedName {
117 &self.browse_name
118 }
119
120 pub fn node_class(&self) -> NodeClass {
122 self.node_class
123 }
124
125 pub fn node_attributes(&self) -> &AddNodeAttributes {
127 &self.node_attributes
128 }
129
130 pub fn type_definition_id(&self) -> &ExpandedNodeId {
132 &self.type_definition_id
133 }
134
135 pub fn status(&self) -> StatusCode {
137 self.status
138 }
139
140 pub fn diagnostic_bits(&self) -> DiagnosticBits {
142 self.diagnostic_bits
143 }
144
145 pub fn set_diagnostic_info(&mut self, diagnostic_info: DiagnosticInfo) {
148 self.diagnostic_info = Some(diagnostic_info);
149 }
150}
151
152impl IntoResult for AddNodeItem {
153 type Result = AddNodesResult;
154
155 fn into_result(self) -> (Self::Result, Option<DiagnosticInfo>) {
156 (
157 AddNodesResult {
158 status_code: self.status,
159 added_node_id: self.result_node_id,
160 },
161 self.diagnostic_info,
162 )
163 }
164}
165
166#[derive(Debug, Clone)]
167pub struct AddReferenceItem {
169 source_node_id: NodeId,
170 reference_type_id: NodeId,
171 target_node_id: ExpandedNodeId,
172 is_forward: bool,
173 diagnostic_bits: DiagnosticBits,
174
175 source_status: StatusCode,
176 target_status: StatusCode,
177 diagnostic_info: Option<DiagnosticInfo>,
178}
179
180impl AddReferenceItem {
181 pub(crate) fn new(item: AddReferencesItem, diagnostic_bits: DiagnosticBits) -> Self {
182 let mut status = StatusCode::BadNotSupported;
183 if item.source_node_id.is_null() {
184 status = StatusCode::BadSourceNodeIdInvalid;
185 }
186 if item.target_node_id.is_null() {
187 status = StatusCode::BadTargetNodeIdInvalid;
188 }
189 if item.reference_type_id.is_null() {
190 status = StatusCode::BadReferenceTypeIdInvalid;
191 }
192 if !item.target_server_uri.is_null() || item.target_node_id.server_index != 0 {
193 status = StatusCode::BadReferenceLocalOnly;
194 }
195 Self {
196 source_node_id: item.source_node_id,
197 reference_type_id: item.reference_type_id,
198 target_node_id: item.target_node_id,
199 is_forward: item.is_forward,
200 source_status: status,
201 target_status: status,
202 diagnostic_bits,
203 diagnostic_info: None,
204 }
205 }
206
207 pub fn source_node_id(&self) -> &NodeId {
209 &self.source_node_id
210 }
211
212 pub fn reference_type_id(&self) -> &NodeId {
214 &self.reference_type_id
215 }
216
217 pub fn target_node_id(&self) -> &ExpandedNodeId {
219 &self.target_node_id
220 }
221
222 pub(crate) fn result_status(&self) -> StatusCode {
224 if self.source_status.is_good() {
225 return self.source_status;
226 }
227 if self.target_status.is_good() {
228 return self.target_status;
229 }
230 self.source_status
231 }
232
233 pub fn set_source_result(&mut self, status: StatusCode) {
235 self.source_status = status;
236 }
237
238 pub fn set_target_result(&mut self, status: StatusCode) {
240 self.target_status = status;
241 }
242
243 pub fn is_forward(&self) -> bool {
245 self.is_forward
246 }
247
248 pub fn target_status(&self) -> StatusCode {
250 self.target_status
251 }
252
253 pub fn source_status(&self) -> StatusCode {
255 self.source_status
256 }
257
258 pub fn diagnostic_bits(&self) -> DiagnosticBits {
260 self.diagnostic_bits
261 }
262
263 pub fn set_diagnostic_info(&mut self, diagnostic_info: DiagnosticInfo) {
266 self.diagnostic_info = Some(diagnostic_info);
267 }
268}
269
270impl IntoResult for AddReferenceItem {
271 type Result = StatusCode;
272
273 fn into_result(self) -> (Self::Result, Option<DiagnosticInfo>) {
274 (self.result_status(), self.diagnostic_info)
275 }
276}
277
278#[derive(Debug)]
279pub struct DeleteNodeItem {
281 node_id: NodeId,
282 delete_target_references: bool,
283 diagnostic_bits: DiagnosticBits,
284
285 status: StatusCode,
286 diagnostic_info: Option<DiagnosticInfo>,
287}
288
289impl DeleteNodeItem {
290 pub(crate) fn new(item: DeleteNodesItem, diagnostic_bits: DiagnosticBits) -> Self {
291 let mut status = StatusCode::BadNodeIdUnknown;
292 if item.node_id.is_null() {
293 status = StatusCode::BadNodeIdInvalid;
294 }
295
296 Self {
297 node_id: item.node_id,
298 delete_target_references: item.delete_target_references,
299 status,
300 diagnostic_bits,
301 diagnostic_info: None,
302 }
303 }
304
305 pub fn status(&self) -> StatusCode {
307 self.status
308 }
309
310 pub fn set_result(&mut self, status: StatusCode) {
312 self.status = status;
313 }
314
315 pub fn delete_target_references(&self) -> bool {
317 self.delete_target_references
318 }
319
320 pub fn node_id(&self) -> &NodeId {
322 &self.node_id
323 }
324
325 pub fn diagnostic_bits(&self) -> DiagnosticBits {
327 self.diagnostic_bits
328 }
329
330 pub fn set_diagnostic_info(&mut self, diagnostic_info: DiagnosticInfo) {
333 self.diagnostic_info = Some(diagnostic_info);
334 }
335}
336
337impl IntoResult for DeleteNodeItem {
338 type Result = StatusCode;
339
340 fn into_result(self) -> (Self::Result, Option<DiagnosticInfo>) {
341 (self.status(), self.diagnostic_info)
342 }
343}
344
345#[derive(Debug)]
346pub struct DeleteReferenceItem {
348 source_node_id: NodeId,
349 reference_type_id: NodeId,
350 is_forward: bool,
351 target_node_id: ExpandedNodeId,
352 delete_bidirectional: bool,
353 diagnostic_bits: DiagnosticBits,
354
355 source_status: StatusCode,
356 target_status: StatusCode,
357 diagnostic_info: Option<DiagnosticInfo>,
358}
359
360impl DeleteReferenceItem {
361 pub(crate) fn new(item: DeleteReferencesItem, diagnostic_bits: DiagnosticBits) -> Self {
362 let mut status = StatusCode::BadNotSupported;
363 if item.source_node_id.is_null() {
364 status = StatusCode::BadSourceNodeIdInvalid;
365 }
366 if item.target_node_id.is_null() {
367 status = StatusCode::BadTargetNodeIdInvalid;
368 }
369 if item.reference_type_id.is_null() {
370 status = StatusCode::BadReferenceTypeIdInvalid;
371 }
372 if item.target_node_id.server_index != 0 {
373 status = StatusCode::BadReferenceLocalOnly;
374 }
375
376 Self {
377 source_node_id: item.source_node_id,
378 reference_type_id: item.reference_type_id,
379 is_forward: item.is_forward,
380 target_node_id: item.target_node_id,
381 delete_bidirectional: item.delete_bidirectional,
382 diagnostic_bits,
383
384 source_status: status,
385 target_status: status,
386 diagnostic_info: None,
387 }
388 }
389
390 pub fn source_node_id(&self) -> &NodeId {
392 &self.source_node_id
393 }
394
395 pub fn reference_type_id(&self) -> &NodeId {
397 &self.reference_type_id
398 }
399
400 pub fn target_node_id(&self) -> &ExpandedNodeId {
402 &self.target_node_id
403 }
404
405 pub(crate) fn result_status(&self) -> StatusCode {
406 if self.source_status.is_good() {
407 return self.source_status;
408 }
409 if self.target_status.is_good() {
410 return self.target_status;
411 }
412 self.source_status
413 }
414
415 pub fn set_source_result(&mut self, status: StatusCode) {
417 self.source_status = status;
418 }
419
420 pub fn set_target_result(&mut self, status: StatusCode) {
422 self.target_status = status;
423 }
424
425 pub fn is_forward(&self) -> bool {
427 self.is_forward
428 }
429
430 pub fn target_status(&self) -> StatusCode {
432 self.target_status
433 }
434
435 pub fn source_status(&self) -> StatusCode {
437 self.source_status
438 }
439
440 pub fn delete_bidirectional(&self) -> bool {
442 self.delete_bidirectional
443 }
444
445 pub fn diagnostic_bits(&self) -> DiagnosticBits {
447 self.diagnostic_bits
448 }
449
450 pub fn set_diagnostic_info(&mut self, diagnostic_info: DiagnosticInfo) {
453 self.diagnostic_info = Some(diagnostic_info);
454 }
455}
456
457impl IntoResult for DeleteReferenceItem {
458 type Result = StatusCode;
459
460 fn into_result(self) -> (Self::Result, Option<DiagnosticInfo>) {
461 (self.result_status(), self.diagnostic_info)
462 }
463}