UABaseNode.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import type { NamespaceTable } from "./NameSpaceTable";
  2. import { coerceNodeId, NodeId } from "./NodeId";
  3. import { UAReference } from "./UAReference";
  4. import { assert } from "@/util/assert";
  5. import { XMLElem, type IToXML } from "@/util/XmlElem";
  6. import { UARolePermission } from "./UARolePermission"; //TODO
  7. import { UAExtension } from "./UAExtension"; //TODO
  8. import { UAUserWriteMask } from "./UAUserWriteMask"; //TODO
  9. import { UAWriteMask } from "./UAWriteMask"; //TODO
  10. import { UAAccessRestriction } from "./UAAccessRestriction"; //TODO
  11. export class UABaseNode implements IToXML{
  12. public nodeId: NodeId;
  13. public nodeClass="UABaseNode";
  14. public browseName: string;
  15. public displayName?: string; //LocText
  16. public description?: string; //LocText
  17. public symbolicName?: string; //SymbolicName
  18. public releaseStatus?: string; //ReleaseStatus
  19. public hasNoPermissions?: boolean;
  20. public writeMask?: UAWriteMask;
  21. public userWriteMask?: UAUserWriteMask;
  22. public category?: string;
  23. public documentation?: string;
  24. public accessRestriction?: UAAccessRestriction;
  25. public rolePermissions: UARolePermission[]=[];
  26. public extensions: UAExtension[]=[];
  27. public references: UAReference[]=[];
  28. public opts: string[]=[];
  29. constructor(options: UABaseNodeOptions) {
  30. this.nodeId=options.nodeId;
  31. this.browseName=options.browseName;
  32. this.displayName=options.displayName;
  33. this.references=options.references||[];
  34. }
  35. public static nullBaseNode=new UABaseNode({browseName: "", nodeId: NodeId.nullNodeId});
  36. reIndex(nst: NamespaceTable, onst: NamespaceTable) {
  37. const nsName=onst.getUri(this.nodeId.namespace);
  38. assert(nsName!=undefined)
  39. const newIndex=nst.getIndex(nsName);
  40. assert(newIndex!=undefined)
  41. this.nodeId.namespace=newIndex;
  42. for(const uaref of this.references) {
  43. uaref.reIndex(nst, onst);
  44. }
  45. }
  46. getParent(): UABaseNode|null {
  47. const ref=this.getParentRef();
  48. if(ref?.fromNode===this)
  49. return ref.toNode;
  50. if(ref?.toNode===this)
  51. return ref.fromNode;
  52. return null;
  53. }
  54. setParent(node: UABaseNode, refType: String) {
  55. }
  56. getParentRef(): UAReference|null{
  57. for(const ref of this.references) {
  58. switch(ref.referenceType) {
  59. case 'HasComponent':
  60. case 'HasOrderedComponent':
  61. case 'Organizes':
  62. case 'HasProperty':
  63. case 'HasSubtype':
  64. case 'HasAddIn':
  65. if(ref.fromNode===this&&ref.isForward===false)
  66. return ref;
  67. if(ref.toNode===this&&ref.isForward===true)
  68. return ref;
  69. }
  70. }
  71. return null;
  72. }
  73. getChildren(): UABaseNode[] {
  74. const children: UABaseNode[]=[];
  75. for(const ref of this.references) {
  76. switch(ref.referenceType) {
  77. case 'HasComponent':
  78. case 'HasOrderedComponent':
  79. case 'Organizes':
  80. case 'HasProperty':
  81. case 'HasSubtype':
  82. case 'HasAddIn':
  83. if(ref.isForward&&ref.fromNode===this) {
  84. if(!children.includes(ref.toNode))
  85. children.push(ref.toNode);
  86. }
  87. if(!ref.isForward&&ref.toNode===this) {
  88. if(!children.includes(ref.fromNode))
  89. children.push(ref.fromNode);
  90. }
  91. break;
  92. }
  93. }
  94. return children;
  95. }
  96. resolveReferences(nm: Map<string, UABaseNode>) {
  97. for(const ref of this.references) {
  98. const fromNode=nm.get(ref.fromRef.toString())
  99. if(fromNode)
  100. ref.fromNode=fromNode;
  101. const toNode=nm.get(ref.toRef.toString())
  102. if(!toNode)
  103. continue; //TODO: if we cant find the node; the parser is still incomplete or the nodeset is broken
  104. ref.toNode=toNode;
  105. if(ref.fromNode.nodeId.toString()===this.nodeId.toString()){ //add this reference to referenced node
  106. //Bug? when loading from filedrop; fromNode is a proxy; this is not.
  107. if(!ref.toNode.references.includes(ref))
  108. ref.toNode.references.push(ref);
  109. }
  110. }
  111. }
  112. static fromXML(xmlObject: any): UABaseNode{
  113. const xmlReferences=xmlObject['References']||[];
  114. const references:UAReference[]=[];
  115. const nodeId=coerceNodeId(xmlObject['@_NodeId']);
  116. for(const xmlref of xmlReferences.Reference||[]) {
  117. references.push(UAReference.fromXML(xmlref, nodeId));
  118. }
  119. const ua=new UABaseNode({nodeId: nodeId,
  120. browseName: xmlObject['@_BrowseName'],
  121. displayName: xmlObject['DisplayName']['#text'],
  122. references: references});
  123. return ua;
  124. }
  125. toXML(lnst: NamespaceTable, gnst: NamespaceTable): XMLElem {
  126. throw new Error("UABaseNode has no xml rep; implement in subtype.");
  127. }
  128. static localNodeId(nodeId: NodeId, lnst: NamespaceTable, gnst: NamespaceTable) {
  129. const ns_uri=gnst.getUri(nodeId.namespace);
  130. assert(ns_uri);
  131. const nsIdx=lnst.getIndex(ns_uri);
  132. assert(nsIdx);
  133. const tmpNode= coerceNodeId(nodeId.toString());
  134. tmpNode.namespace=nsIdx;
  135. return tmpNode;
  136. }
  137. }
  138. export interface UABaseNodeOptions {
  139. browseName: string;
  140. namespace?: string;
  141. nodeId: NodeId;
  142. references?: UAReference[];
  143. displayName?: string;
  144. description?: string
  145. }