node-opcua-address-space 2.151.0 → 2.153.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 (52) hide show
  1. package/dist/source/helpers/dump_tools.d.ts +1 -1
  2. package/dist/source/helpers/dump_tools.js.map +1 -1
  3. package/dist/source/loader/load_nodeset2.js +1 -7
  4. package/dist/source/loader/load_nodeset2.js.map +1 -1
  5. package/dist/source/ua_addin.d.ts +4 -1
  6. package/dist/source/ua_addin.js +3 -2
  7. package/dist/source/ua_addin.js.map +1 -1
  8. package/dist/src/address_space.d.ts +1 -1
  9. package/dist/src/address_space.js +10 -4
  10. package/dist/src/address_space.js.map +1 -1
  11. package/dist/src/address_space_change_event_tools.js +13 -11
  12. package/dist/src/address_space_change_event_tools.js.map +1 -1
  13. package/dist/src/address_space_private.d.ts +1 -1
  14. package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.js +2 -2
  15. package/dist/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.js.map +1 -1
  16. package/dist/src/base_node_impl.d.ts +13 -6
  17. package/dist/src/base_node_impl.js +129 -102
  18. package/dist/src/base_node_impl.js.map +1 -1
  19. package/dist/src/base_node_private.d.ts +16 -10
  20. package/dist/src/base_node_private.js +80 -27
  21. package/dist/src/base_node_private.js.map +1 -1
  22. package/dist/src/namespace_impl.d.ts +1 -2
  23. package/dist/src/namespace_impl.js +12 -7
  24. package/dist/src/namespace_impl.js.map +1 -1
  25. package/dist/src/namespace_private.d.ts +1 -1
  26. package/dist/src/namespace_private.js.map +1 -1
  27. package/dist/src/nodeid_manager.d.ts +4 -4
  28. package/dist/src/nodeid_manager.js +3 -1
  29. package/dist/src/nodeid_manager.js.map +1 -1
  30. package/dist/src/reference_impl.js.map +1 -1
  31. package/dist/src/state_machine/finite_state_machine.d.ts +1 -4
  32. package/dist/src/state_machine/finite_state_machine.js.map +1 -1
  33. package/dist/tsconfig_common.tsbuildinfo +1 -1
  34. package/distHelpers/boiler_system.js +11 -0
  35. package/distHelpers/boiler_system.js.map +1 -1
  36. package/distHelpers/create_minimalist_address_space_nodeset.js +2 -0
  37. package/distHelpers/create_minimalist_address_space_nodeset.js.map +1 -1
  38. package/package.json +35 -34
  39. package/source/helpers/dump_tools.ts +4 -1
  40. package/source/loader/load_nodeset2.ts +4 -9
  41. package/source/ua_addin.ts +8 -3
  42. package/src/address_space.ts +13 -6
  43. package/src/address_space_change_event_tools.ts +16 -12
  44. package/src/address_space_private.ts +1 -1
  45. package/src/alarms_and_conditions/ua_certificate_expiration_alarm_impl.ts +4 -3
  46. package/src/base_node_impl.ts +167 -123
  47. package/src/base_node_private.ts +134 -76
  48. package/src/namespace_impl.ts +26 -22
  49. package/src/namespace_private.ts +4 -1
  50. package/src/nodeid_manager.ts +14 -10
  51. package/src/reference_impl.ts +1 -3
  52. package/src/state_machine/finite_state_machine.ts +1 -2
@@ -19,7 +19,9 @@ import {
19
19
  UAReferenceType,
20
20
  IAddressSpace,
21
21
  INamespace,
22
- BrowseDescriptionOptions2
22
+ BrowseDescriptionOptions2,
23
+ UAVariableT,
24
+ UAProperty
23
25
  } from "node-opcua-address-space-base";
24
26
  import { assert } from "node-opcua-assert";
25
27
  import {
@@ -39,7 +41,7 @@ import {
39
41
  } from "node-opcua-data-model";
40
42
  import { DataValue } from "node-opcua-data-value";
41
43
  import { dumpIf, make_debugLog, make_warningLog, make_errorLog } from "node-opcua-debug";
42
- import { coerceNodeId, makeNodeId, NodeId, NodeIdLike, resolveNodeId, sameNodeId } from "node-opcua-nodeid";
44
+ import { coerceNodeId, makeNodeId, NodeId, NodeIdLike, NodeIdType, resolveNodeId, sameNodeId } from "node-opcua-nodeid";
43
45
  import { NumericRange } from "node-opcua-numeric-range";
44
46
  import { ReferenceDescription } from "node-opcua-service-browse";
45
47
  import { StatusCode, StatusCodes } from "node-opcua-status-code";
@@ -54,7 +56,7 @@ import { lowerFirstLetter } from "node-opcua-utils";
54
56
  import { DataType, VariantArrayType } from "node-opcua-variant";
55
57
 
56
58
  import { UAStateVariable } from "node-opcua-nodeset-ua";
57
- import { ObjectTypeIds, VariableTypeIds } from "node-opcua-constants";
59
+ import { ObjectTypeIds, ReferenceTypeIds, VariableTypeIds } from "node-opcua-constants";
58
60
 
59
61
  import { XmlWriter } from "../source/xml_writer";
60
62
  import { dumpReferenceDescriptions, dumpReferences } from "../source/helpers/dump_tools";
@@ -65,18 +67,22 @@ import { AddressSpacePrivate } from "./address_space_private";
65
67
  import {
66
68
  _constructReferenceDescription,
67
69
  _handle_HierarchicalReference,
70
+ _get_HierarchicalReference,
71
+ _remove_HierarchicalReference,
68
72
  BaseNode_add_backward_reference,
73
+ BaseNode_remove_backward_reference,
69
74
  BaseNode_getPrivate,
70
75
  BaseNode_initPrivate,
71
- BaseNode_remove_backward_reference,
72
76
  BaseNode_removePrivate,
73
77
  BaseNode_toString,
74
78
  ToStringBuilder,
75
79
  BaseNode_getCache,
76
- BaseNode_clearCache
80
+ BaseNode_clearCache,
81
+ HierarchicalIndexMap,
77
82
  } from "./base_node_private";
78
83
  import { MinimalistAddressSpace, ReferenceImpl } from "./reference_impl";
79
84
  import { coerceRolePermissions } from "./role_permissions";
85
+ import { UAString } from "node-opcua-basic-types";
80
86
 
81
87
  // tslint:disable:no-var-requires
82
88
  // tslint:disable:no-bitwise
@@ -303,7 +309,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
303
309
  public readonly nodeId: NodeId;
304
310
  public readonly browseName: QualifiedName;
305
311
 
306
- protected _postInstantiateFunc?: any;
312
+ protected _postInstantiateFunc?: (instance: BaseNode, instanceType: BaseNode, options?: any) => void;
307
313
 
308
314
  /**
309
315
  * @internal
@@ -389,9 +395,8 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
389
395
  const isForward = browseDirection === BrowseDirection.Forward;
390
396
  const results: UAReference[] = [];
391
397
 
392
- const process = (referenceIdx: { [key: string]: UAReference }) => {
393
- const references = Object.values(referenceIdx);
394
- for (const ref of references) {
398
+ const process = (referenceIdx: Map<string, UAReference>) => {
399
+ for (const ref of referenceIdx.values()) {
395
400
  if (ref.isForward === isForward && referenceTypeNode && referenceTypeNode.checkHasSubtype(ref.referenceType)) {
396
401
  results.push(ref);
397
402
  }
@@ -406,7 +411,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
406
411
  public findReferences_no_cache(referenceTypeNode: UAReferenceType, isForward = true): UAReference[] {
407
412
  const _private = BaseNode_getPrivate(this);
408
413
  const result: UAReference[] = [];
409
- for (const ref of Object.values(_private._referenceIdx)) {
414
+ for (const ref of _private._referenceIdx.values()) {
410
415
  if (ref.isForward === isForward) {
411
416
  if (sameNodeId(ref.referenceType, referenceTypeNode.nodeId)) {
412
417
  result.push(ref);
@@ -414,7 +419,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
414
419
  }
415
420
  }
416
421
 
417
- for (const ref of Object.values(_private._back_referenceIdx)) {
422
+ for (const ref of _private._back_referenceIdx.values()) {
418
423
  if (ref.isForward === isForward) {
419
424
  if (sameNodeId(ref.referenceType, referenceTypeNode.nodeId)) {
420
425
  result.push(ref);
@@ -432,8 +437,11 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
432
437
  // throw new Error("expecting valid reference name " + strReference);
433
438
  return [];
434
439
  }
440
+
435
441
  _cache._ref = _cache._ref || new Map();
436
- const hash = "_ref_" + referenceTypeNode.nodeId.toString() + isForward.toString();
442
+
443
+ const hash = `r|${referenceTypeNode.nodeId.toString()}|${isForward ? "f" : "b"}`;
444
+
437
445
  if (_cache._ref.has(hash)) {
438
446
  return _cache._ref.get(hash)!;
439
447
  }
@@ -471,11 +479,6 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
471
479
  * return an array with the Aggregates of this object.
472
480
  */
473
481
  public getAggregates(): BaseNode[] {
474
- // const _cache = BaseNode_getCache(this);
475
- // if (!_cache._aggregates) {
476
- // _cache._aggregates = this.findReferencesExAsObject("Aggregates", BrowseDirection.Forward);
477
- // }
478
- // return _cache._aggregates;
479
482
  return this.findReferencesExAsObject("Aggregates", BrowseDirection.Forward);
480
483
  }
481
484
 
@@ -483,11 +486,6 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
483
486
  * return an array with the components of this object.
484
487
  */
485
488
  public getComponents(): BaseNode[] {
486
- // const _cache = BaseNode_getCache(this);
487
- // if (!_cache._components) {
488
- // _cache._components = this.findReferencesExAsObject("HasComponent", BrowseDirection.Forward);
489
- // }
490
- // return _cache._components;
491
489
  return this.findReferencesExAsObject("HasComponent", BrowseDirection.Forward);
492
490
  }
493
491
 
@@ -495,24 +493,24 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
495
493
  * return a array with the properties of this object.
496
494
  */
497
495
  public getProperties(): BaseNode[] {
498
- // const _cache = BaseNode_getCache(this);
499
- // if (!_cache._properties) {
500
- // _cache._properties = this.findReferencesExAsObject("HasProperty", BrowseDirection.Forward);
501
- // }
502
- // return _cache._properties;
503
496
  return this.findReferencesExAsObject("HasProperty", BrowseDirection.Forward);
504
497
  }
505
498
 
499
+ private static _hasChild: NodeId = new NodeId(NodeIdType.NUMERIC, ReferenceTypeIds.HasChild);
500
+ public getChildren(): BaseNode[] {
501
+ // return this.findReferencesExAsObject(BaseNodeImpl._hasChild, BrowseDirection.Forward);
502
+ const _cache = BaseNode_getCache(this);
503
+ if (!_cache._children) {
504
+ _cache._children = this.findReferencesExAsObject(BaseNodeImpl._hasChild, BrowseDirection.Forward);
505
+ };
506
+ return _cache._children;
507
+ }
508
+
506
509
  /**
507
510
  * return a array with the notifiers of this object.
508
511
  * only reference of exact type HasNotifier are returned.
509
512
  */
510
513
  public getNotifiers(): BaseNode[] {
511
- // const _cache = BaseNode_getCache(this);
512
- // if (!_cache._notifiers) {
513
- // _cache._notifiers = this.findReferencesAsObject("HasNotifier", true);
514
- // }
515
- // return _cache._notifiers;
516
514
  return this.findReferencesAsObject(HasNotifierReferenceType, true);
517
515
  }
518
516
 
@@ -521,11 +519,6 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
521
519
  * only reference of exact type HasEventSource are returned.
522
520
  */
523
521
  public getEventSources(): BaseNode[] {
524
- // const _cache = BaseNode_getCache(this);
525
- // if (!_cache._eventSources) {
526
- // _cache._eventSources = this.findReferencesAsObject("HasEventSource", true);
527
- // }
528
- // return _cache._eventSources;
529
522
  return this.findReferencesAsObject(HasEventSourceReferenceType, true);
530
523
  }
531
524
 
@@ -533,11 +526,6 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
533
526
  * return a array of the objects for which this node is an EventSource
534
527
  */
535
528
  public getEventSourceOfs(): BaseNode[] {
536
- // const _cache = BaseNode_getCache(this);
537
- // if (!_cache._eventSources) {
538
- // _cache._eventSources = this.findReferencesAsObject("HasEventSource", false);
539
- // }
540
- // return _cache._eventSources;
541
529
  return this.findReferencesAsObject(HasEventSourceReferenceType, false);
542
530
  }
543
531
 
@@ -604,12 +592,6 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
604
592
  * Note: internally, methods are special types of components
605
593
  */
606
594
  public getMethods(): UAMethod[] {
607
- // const _cache = BaseNode_getCache(this);
608
- // if (!_cache._methods) {
609
- // const components = this.getComponents();
610
- // _cache._methods = components.filter((obj) => obj.nodeClass === NodeClass.Method) as UAMethod[];
611
- // }
612
- // return _cache._methods;
613
595
  const components = this.getComponents();
614
596
  return components.filter((obj) => obj.nodeClass === NodeClass.Method) as UAMethod[];
615
597
  }
@@ -741,7 +723,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
741
723
 
742
724
  public ownReferences(): UAReference[] {
743
725
  const _private = BaseNode_getPrivate(this);
744
- return Object.values(_private._referenceIdx);
726
+ return [..._private._referenceIdx.values()];
745
727
  }
746
728
 
747
729
  /**
@@ -871,7 +853,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
871
853
  /* istanbul ignore next */
872
854
  if (do_debug) {
873
855
  debugLog("all references :", this.nodeId.toString(), this.browseName.toString());
874
- dumpReferences(addressSpace, (Object as any).values(_private._referenceIdx));
856
+ dumpReferences(addressSpace, _private._referenceIdx.values());
875
857
  }
876
858
 
877
859
  // filter out references not matching referenceType
@@ -898,7 +880,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
898
880
 
899
881
  public allReferences(): UAReference[] {
900
882
  const _private = BaseNode_getPrivate(this);
901
- return Object.values(_private._referenceIdx).concat(Object.values(_private._back_referenceIdx));
883
+ return [..._private._referenceIdx.values(), ..._private._back_referenceIdx.values()];
902
884
  }
903
885
 
904
886
  /**
@@ -916,16 +898,14 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
916
898
  * myDevice1.addReference({ referenceType: "OrganizedBy", nodeId: view });
917
899
  */
918
900
  public addReference(reference: AddReferenceOpts): void {
919
- const referenceNode = this.__addReference(reference);
920
901
 
902
+ const referenceNode = this.__addReference(reference);
921
903
  const addressSpace = this.addressSpace;
922
904
 
923
905
  if (!resolveReferenceType(addressSpace, referenceNode)) {
924
906
  throw new Error("BaseNode#addReference : invalid reference " + reference.toString());
925
907
  }
926
908
 
927
- this._clear_caches();
928
-
929
909
  _propagate_ref.call(this, addressSpace, referenceNode);
930
910
  this.install_extra_properties();
931
911
  _handle_add_reference_change_event(this, referenceNode.nodeId);
@@ -945,26 +925,25 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
945
925
 
946
926
  const relatedNode = addressSpace.findNode(reference.nodeId)!;
947
927
 
948
- const invReference = new ReferenceImpl({
928
+ const backwardReference = new ReferenceImpl({
949
929
  isForward: !reference.isForward,
950
930
  nodeId: this.nodeId,
951
931
  referenceType: reference.referenceType
952
932
  });
953
933
 
954
- if (_private._referenceIdx[h]) {
955
- delete _private._referenceIdx[h];
956
- BaseNode_remove_backward_reference.call(relatedNode as BaseNode, invReference);
957
- } else if (_private._back_referenceIdx[h]) {
958
- (relatedNode as any).removeReference(invReference);
934
+ if (_private._referenceIdx.has(h)) {
935
+ _private._referenceIdx.delete(h);
936
+ BaseNode_remove_backward_reference.call(relatedNode as BaseNodeImpl, backwardReference);
937
+ _remove_HierarchicalReference(this, reference);
938
+ this.uninstall_extra_properties(reference);
939
+ this._clear_caches();
940
+
941
+ } else if (_private._back_referenceIdx.has(h)) {
942
+ return relatedNode.removeReference(backwardReference);
959
943
  } else {
960
- // throw new Error("Cannot find reference " + reference);
944
+ warningLog("Cannot find reference to remove: " + reference.toString());
961
945
  }
962
946
 
963
- _handle_HierarchicalReference(this, reference);
964
-
965
- this.uninstall_extra_properties(reference);
966
-
967
- this._clear_caches();
968
947
  }
969
948
 
970
949
  /**
@@ -1095,29 +1074,42 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1095
1074
 
1096
1075
  public getChildByName(browseName: QualifiedNameOptions): BaseNode | null;
1097
1076
  public getChildByName(browseName: string, namespaceIndex?: number): BaseNode | null;
1077
+ //
1098
1078
  public getChildByName(browseName: QualifiedNameLike, namespaceIndex?: number): BaseNode | null {
1099
- // Attention: getChild doesn't care about namespace on browseName
1100
- // !!!!
1101
- if (browseName instanceof QualifiedName) {
1102
- browseName = browseName.name!.toString();
1103
- }
1104
- assert(typeof browseName === "string");
1105
1079
 
1106
- const _cache = BaseNode_getCache(this);
1107
-
1108
- const addressSpace = this.addressSpace;
1109
-
1110
- if (!_cache._childByNameMap) {
1111
- _cache._childByNameMap = new Map();
1112
-
1113
- const childReferenceTypes = this.findReferencesEx("HasChild");
1114
- for (const r of childReferenceTypes) {
1115
- const child = resolveReferenceNode(addressSpace, r);
1116
- _cache._childByNameMap.set(child.browseName.name!.toString(),child);
1117
- }
1080
+ var childrenMap = _get_HierarchicalReference(this);
1081
+ const select = _select_by_browse_name(childrenMap, browseName, namespaceIndex);
1082
+ if (select.length == 0) {
1083
+ return null;
1084
+ }
1085
+ const ref = select[0];
1086
+ const r = this.addressSpace.findReferenceType(ref.referenceType);
1087
+ if (!r) return null;
1088
+ const hasChild = this.addressSpace.findReferenceType("HasChild");
1089
+ if (!hasChild) {
1090
+ return null; // too early, bmy be namespace 0 is still loading
1091
+ }
1092
+ if (r.isSubtypeOf(hasChild)) {
1093
+ return ref.node!;
1118
1094
  }
1119
- const ret = _cache._childByNameMap.get(browseName.toString()) || null;
1120
- return ret;
1095
+ return null;
1096
+ }
1097
+ public getNodeVersion(): UAProperty<UAString, DataType.String> | null {
1098
+ return this.getChildByName("NodeVersion", 0) as UAProperty<UAString, DataType.String> | null;
1099
+ /*
1100
+ const cache = BaseNode_getCache(this);
1101
+ if (cache._versionNode == undefined) {
1102
+ cache._versionNode = this.getChildByName("NodeVersion", 0) as UAProperty<string, DataType.String> | null;
1103
+ }
1104
+ return cache._versionNode as UAProperty<UAString, DataType.String> | null;
1105
+ */
1106
+ }
1107
+
1108
+ public get nodeVersion(): UAProperty<UAString, DataType.String> | undefined {
1109
+ return this.getNodeVersion() || undefined;
1110
+ }
1111
+ public set nodeVersion(n: any) {
1112
+ assert(false);
1121
1113
  }
1122
1114
 
1123
1115
  get toStateNode(): BaseNode | null {
@@ -1135,6 +1127,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1135
1127
  /**
1136
1128
  * this methods propagates the forward references to the pointed node
1137
1129
  * by inserting backward references to the counter part node
1130
+ * @private
1138
1131
  */
1139
1132
  public propagate_back_references(): void {
1140
1133
  const _private = BaseNode_getPrivate(this);
@@ -1144,7 +1137,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1144
1137
  return;
1145
1138
  }
1146
1139
  const addressSpace = this.addressSpace;
1147
- for (const reference of Object.values(_private._referenceIdx)) {
1140
+ for (const reference of _private._referenceIdx.values()) {
1148
1141
  _propagate_ref.call(this, addressSpace, reference);
1149
1142
  }
1150
1143
  }
@@ -1153,8 +1146,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1153
1146
  * the dispose method should be called when the node is no longer used, to release
1154
1147
  * back pointer to the address space and clear caches.
1155
1148
  *
1156
-
1157
- *
1149
+ * @private
1158
1150
  */
1159
1151
  public dispose(): void {
1160
1152
  this.emit("dispose");
@@ -1163,8 +1155,13 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1163
1155
  this._clear_caches();
1164
1156
 
1165
1157
  const _private = BaseNode_getPrivate(this);
1166
- Object.values(_private._back_referenceIdx).forEach((ref) => (ref as ReferenceImpl).dispose());
1167
- Object.values(_private._referenceIdx).forEach((ref) => (ref as ReferenceImpl).dispose());
1158
+ for (let ref of _private._back_referenceIdx.values()) {
1159
+ (ref as ReferenceImpl).dispose();
1160
+ }
1161
+
1162
+ for (let ref of _private._referenceIdx.values()) {
1163
+ (ref as ReferenceImpl).dispose();
1164
+ }
1168
1165
 
1169
1166
  BaseNode_removePrivate(this);
1170
1167
  }
@@ -1188,7 +1185,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1188
1185
 
1189
1186
  const addressSpace = this.addressSpace;
1190
1187
 
1191
- for (const reference of Object.values(_private._referenceIdx) as UAReference[]) {
1188
+ for (const reference of _private._referenceIdx.values()) {
1192
1189
  // filter out non Hierarchical References
1193
1190
  const referenceType = resolveReferenceType(addressSpace, reference);
1194
1191
 
@@ -1197,7 +1194,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1197
1194
  console.error(chalk.red(" ERROR"), " cannot find reference ", reference.referenceType, reference.toString());
1198
1195
  }
1199
1196
 
1200
- const related_node = resolveReferenceNode(addressSpace, reference) as BaseNode;
1197
+ const related_node = resolveReferenceNode(addressSpace, reference) as BaseNodeImpl;
1201
1198
  if (related_node) {
1202
1199
  assert(reference.nodeId.toString() !== this.nodeId.toString());
1203
1200
  BaseNode_remove_backward_reference.call(
@@ -1212,7 +1209,7 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1212
1209
  }
1213
1210
  }
1214
1211
 
1215
- public installPostInstallFunc(f: () => void): void {
1212
+ public installPostInstallFunc(f: (instance: BaseNode, tpyeNode: BaseNode, opts?: any) => void): void {
1216
1213
  if (!f) {
1217
1214
  // nothing to do
1218
1215
  return;
@@ -1232,8 +1229,20 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1232
1229
  this._postInstantiateFunc = chain.call(this, this._postInstantiateFunc, f);
1233
1230
  }
1234
1231
 
1235
- public _on_child_added(): void {
1232
+ public _on_child_added(childNode: BaseNode): void {
1233
+
1234
+ // this._clear_caches();
1235
+ // return;
1236
+ const cache = BaseNode_getCache(this);
1237
+ const tmpV = cache._versionNode;
1238
+ const tmpC = cache._children;
1236
1239
  this._clear_caches();
1240
+ const newCache = BaseNode_getCache(this);
1241
+ newCache._versionNode = tmpV;
1242
+ newCache._children = tmpC;
1243
+ if (newCache._children) {
1244
+ newCache._children!.push(childNode);
1245
+ }
1237
1246
  }
1238
1247
 
1239
1248
  public _on_child_removed(obj: BaseNode): void {
@@ -1272,22 +1281,23 @@ export class BaseNodeImpl extends EventEmitter implements BaseNode {
1272
1281
  }
1273
1282
 
1274
1283
  private __addReference(referenceOpts: AddReferenceOpts): UAReference {
1275
- const _private = BaseNode_getPrivate(this);
1276
1284
 
1285
+ const addressSpace = this.addressSpace as AddressSpacePrivate;
1286
+ const _private = BaseNode_getPrivate(this);
1277
1287
  assert(Object.prototype.hasOwnProperty.call(referenceOpts, "referenceType"));
1278
1288
  // xx isForward is optional : assert(Object.prototype.hasOwnProperty.call(reference,"isForward"));
1279
1289
  assert(Object.prototype.hasOwnProperty.call(referenceOpts, "nodeId"));
1280
1290
 
1281
- const addressSpace = this.addressSpace as AddressSpacePrivate;
1282
1291
  const reference: UAReference = addressSpace.normalizeReferenceTypes([referenceOpts])[0];
1283
1292
  assert(reference instanceof ReferenceImpl);
1284
1293
 
1285
1294
  const h = (<ReferenceImpl>reference).hash;
1286
- assert(!_private._back_referenceIdx[h], "reference exists already in _back_references");
1287
- assert(!_private._referenceIdx[h], "reference exists already in _references");
1295
+ assert(!_private._back_referenceIdx.has(h), "reference exists already in _back_references");
1296
+ assert(!_private._referenceIdx.has(h), "reference exists already in _references");
1288
1297
 
1289
- _private._referenceIdx[h] = reference;
1298
+ _private._referenceIdx.set(h, reference);
1290
1299
  _handle_HierarchicalReference(this, reference);
1300
+ this._clear_caches();
1291
1301
  return reference;
1292
1302
  }
1293
1303
 
@@ -1474,15 +1484,16 @@ function toString_ReferenceDescription(ref: UAReference, options: { addressSpace
1474
1484
  return str;
1475
1485
  }
1476
1486
 
1477
- function _setup_parent_item(this: BaseNode, references: { [key: string]: any }): BaseNode | null {
1478
- references = Object.values(references);
1487
+ function _setup_parent_item(this: BaseNode, referencesMap: Map<string, UAReference>): BaseNode | null {
1488
+
1489
+ let references: UAReference[] | MapIterator<UAReference> = referencesMap.values();
1479
1490
 
1480
1491
  const _private = BaseNode_getPrivate(this);
1481
1492
  assert(!_private._parent, "_setup_parent_item has been already called");
1482
1493
 
1483
1494
  const addressSpace = this.addressSpace;
1484
1495
 
1485
- if (references.length > 0) {
1496
+ if (referencesMap.size > 0) {
1486
1497
  references = this.findReferencesEx("Aggregates", BrowseDirection.Inverse);
1487
1498
 
1488
1499
  if (references.length >= 1) {
@@ -1510,31 +1521,67 @@ function _setup_parent_item(this: BaseNode, references: { [key: string]: any }):
1510
1521
  return null;
1511
1522
  }
1512
1523
 
1524
+ function toObject(addressSpace: IAddressSpace, reference: UAReference): BaseNode {
1525
+ const obj = resolveReferenceNode(addressSpace, reference);
1526
+ // istanbul ignore next
1527
+ if (doDebug && !obj) {
1528
+ debugLog(
1529
+ chalk.red(" Warning : object with nodeId ") +
1530
+ chalk.cyan(reference.nodeId.toString()) +
1531
+ chalk.red(" cannot be found in the address space !")
1532
+ );
1533
+ }
1534
+ return obj;
1535
+ }
1536
+
1537
+
1513
1538
  function _asObject<T extends BaseNode>(references: UAReference[], addressSpace: IAddressSpace): T[] {
1514
- function toObject(reference: UAReference): T {
1515
- const obj = resolveReferenceNode(addressSpace, reference);
1516
- // istanbul ignore next
1517
- if (doDebug && !obj) {
1518
- debugLog(
1519
- chalk.red(" Warning : object with nodeId ") +
1520
- chalk.cyan(reference.nodeId.toString()) +
1521
- chalk.red(" cannot be found in the address space !")
1522
- );
1539
+
1540
+ return references.map((a) => toObject(addressSpace, a)).filter((o) => o != null && o != undefined) as T[];
1541
+ }
1542
+
1543
+ function _select_by_browse_name(
1544
+ map: HierarchicalIndexMap,
1545
+ browseName: QualifiedNameLike, namespaceIndex?: number
1546
+ ): UAReference[] {
1547
+
1548
+ if ((namespaceIndex === null || namespaceIndex === undefined) && typeof browseName === "string") {
1549
+
1550
+ // no namespace specified and needed
1551
+ const result = map.get(browseName);
1552
+ if (result) {
1553
+ if (Array.isArray(result)) {
1554
+ return result;
1555
+ }
1556
+ return [result];
1523
1557
  }
1524
- return obj as any as T;
1525
- }
1526
1558
 
1527
- function remove_null(o: any): boolean {
1528
- return !!o;
1559
+ } else {
1560
+ const _browseName = coerceQualifiedName(
1561
+ typeof browseName === "string" ? { name: browseName, namespaceIndex } : browseName
1562
+ )!;
1563
+ const result = map.get(_browseName.name || "");
1564
+ if (result) {
1565
+ if (Array.isArray(result)) {
1566
+ // only select the one with the matching namepsace index
1567
+ return result.filter((t) => t.node.browseName.namespaceIndex == _browseName.namespaceIndex);
1568
+ } else {
1569
+ if (result.node.browseName.namespaceIndex == _browseName.namespaceIndex) {
1570
+ return [result];
1571
+ }
1572
+ return [];
1573
+ }
1574
+ }
1529
1575
  }
1576
+ return [];
1530
1577
 
1531
- return references.map(toObject)!.filter(remove_null)! as T[];
1532
1578
  }
1533
1579
 
1534
1580
  function _filter_by_browse_name<T extends BaseNode>(components: T[], browseName: QualifiedNameLike, namespaceIndex?: number): T[] {
1535
1581
  let select: T[] = [];
1536
1582
  if ((namespaceIndex === null || namespaceIndex === undefined) && typeof browseName === "string") {
1537
- select = components.filter((c: T) => c.browseName.name!.toString() === browseName);
1583
+
1584
+ select = components.filter((c: T) => c.browseName.name === browseName);
1538
1585
  if (select && select.length > 1) {
1539
1586
  warningLog("Multiple children exist with name ", browseName, " please specify a namespace index");
1540
1587
  }
@@ -1562,8 +1609,7 @@ function _propagate_ref(this: BaseNode, addressSpace: MinimalistAddressSpace, re
1562
1609
 
1563
1610
  // istanbul ignore next
1564
1611
  if (!referenceType) {
1565
- // tslint:disable-next-line:no-console
1566
- console.error(chalk.red(" ERROR"), " cannot find reference ", reference.referenceType, reference.toString());
1612
+ errorLog(chalk.red(" ERROR"), " cannot find reference ", reference.referenceType, reference.toString());
1567
1613
  }
1568
1614
 
1569
1615
  // ------------------------------- Filter out back reference when reference type
@@ -1575,9 +1621,7 @@ function _propagate_ref(this: BaseNode, addressSpace: MinimalistAddressSpace, re
1575
1621
  if (!referenceType || _is_massively_used_reference(referenceType)) {
1576
1622
  return;
1577
1623
  }
1578
- // ------------------------------- EXPERIMENT
1579
1624
 
1580
- // xx if (!referenceType.isSubtypeOf(hierarchicalReferencesId)) { return; }
1581
1625
  const related_node = resolveReferenceNode(addressSpace, reference) as BaseNodeImpl;
1582
1626
  if (related_node) {
1583
1627
  // verify that reference doesn't point to object it this (see mantis 3099)
@@ -1585,7 +1629,7 @@ function _propagate_ref(this: BaseNode, addressSpace: MinimalistAddressSpace, re
1585
1629
  // istanbul ignore next
1586
1630
  if (displayWarningReferencePointingToItSelf) {
1587
1631
  // this could happen with method
1588
- console.warn(" Warning: a Reference is pointing to this ", this.nodeId.toString(), this.browseName.toString());
1632
+ warningLog(" Warning: a Reference is pointing to source ", this.nodeId.toString(), this.browseName.toString(), ". Is this intentional ?");
1589
1633
  displayWarningReferencePointingToItSelf = false;
1590
1634
  }
1591
1635
  }