@hpcc-js/comms 3.15.4 → 3.15.6

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 (130) hide show
  1. package/LICENSE +43 -43
  2. package/README.md +50 -50
  3. package/dist/browser/index.js +1 -1
  4. package/dist/browser/index.js.map +1 -1
  5. package/dist/browser/index.umd.cjs +1 -1
  6. package/dist/browser/index.umd.cjs.map +1 -1
  7. package/dist/node/index.cjs +10 -10
  8. package/dist/node/index.cjs.map +4 -4
  9. package/dist/node/index.js +9 -9
  10. package/dist/node/index.js.map +4 -4
  11. package/package.json +7 -7
  12. package/src/__package__.ts +3 -3
  13. package/src/clienttools/eclMeta.ts +506 -506
  14. package/src/clienttools/eclcc.ts +628 -628
  15. package/src/connection.ts +288 -288
  16. package/src/ecl/activity.ts +82 -82
  17. package/src/ecl/dfuWorkunit.ts +363 -363
  18. package/src/ecl/graph.ts +196 -196
  19. package/src/ecl/logicalFile.ts +196 -196
  20. package/src/ecl/machine.ts +63 -63
  21. package/src/ecl/query.ts +265 -265
  22. package/src/ecl/queryGraph.ts +813 -813
  23. package/src/ecl/resource.ts +39 -39
  24. package/src/ecl/result.ts +245 -245
  25. package/src/ecl/scope.ts +188 -188
  26. package/src/ecl/sourceFile.ts +34 -34
  27. package/src/ecl/store.ts +154 -154
  28. package/src/ecl/targetCluster.ts +149 -149
  29. package/src/ecl/timer.ts +42 -42
  30. package/src/ecl/topology.ts +131 -131
  31. package/src/ecl/workunit.ts +1340 -1340
  32. package/src/ecl/xsdParser.ts +267 -267
  33. package/src/espConnection.ts +164 -164
  34. package/src/index.browser.ts +1 -1
  35. package/src/index.common.ts +40 -40
  36. package/src/index.node.ts +48 -48
  37. package/src/pem/trustwave.ts +909 -909
  38. package/src/services/fileSpray.ts +73 -73
  39. package/src/services/wsAccess.ts +8 -8
  40. package/src/services/wsAccount.ts +27 -27
  41. package/src/services/wsCloud.ts +73 -73
  42. package/src/services/wsCodesign.ts +18 -18
  43. package/src/services/wsDFU.ts +34 -34
  44. package/src/services/wsDFUXRef.ts +121 -121
  45. package/src/services/wsDali.ts +8 -8
  46. package/src/services/wsEcl.ts +123 -123
  47. package/src/services/wsElk.ts +8 -8
  48. package/src/services/wsLogaccess.ts +270 -270
  49. package/src/services/wsMachine.ts +89 -89
  50. package/src/services/wsPackageProcess.ts +8 -8
  51. package/src/services/wsResources.ts +8 -8
  52. package/src/services/wsSMC.ts +80 -80
  53. package/src/services/wsSasha.ts +7 -7
  54. package/src/services/wsStore.ts +32 -32
  55. package/src/services/wsTopology.ts +45 -45
  56. package/src/services/wsWorkunits.ts +151 -151
  57. package/src/services/wsdl/FileSpray/v1.23/FileSpray.ts +1008 -1008
  58. package/src/services/wsdl/FileSpray/v1.25/FileSpray.ts +1040 -1040
  59. package/src/services/wsdl/FileSpray/v1.26/FileSpray.ts +929 -929
  60. package/src/services/wsdl/FileSpray/v1.27/FileSpray.ts +930 -930
  61. package/src/services/wsdl/WsCloud/v1/WsCloud.ts +38 -38
  62. package/src/services/wsdl/WsCloud/v1.02/WsCloud.ts +77 -77
  63. package/src/services/wsdl/WsDFUXRef/v1.02/WsDFUXRef.ts +224 -224
  64. package/src/services/wsdl/WsDFUXRef/v1.04/WsDFUXRef.ts +228 -227
  65. package/src/services/wsdl/WsDali/v1.04/WsDali.ts +216 -216
  66. package/src/services/wsdl/WsDali/v1.07/WsDali.ts +72 -72
  67. package/src/services/wsdl/WsDfu/v1.62/WsDfu.ts +1455 -1455
  68. package/src/services/wsdl/WsDfu/v1.63/WsDfu.ts +1465 -1465
  69. package/src/services/wsdl/WsDfu/v1.65/WsDfu.ts +1244 -1244
  70. package/src/services/wsdl/WsDfu/v1.66/WsDfu.ts +1267 -1267
  71. package/src/services/wsdl/WsDfu/v1.67/WsDfu.ts +1268 -1268
  72. package/src/services/wsdl/WsDfu/v1.68/WsDfu.ts +1301 -0
  73. package/src/services/wsdl/WsESDLConfig/v1.5/WsESDLConfig.ts +366 -0
  74. package/src/services/wsdl/WsFileIO/v1.01/WsFileIO.ts +104 -104
  75. package/src/services/wsdl/WsPackageProcess/v1.04/WsPackageProcess.ts +519 -519
  76. package/src/services/wsdl/WsPackageProcess/v1.07/WsPackageProcess.ts +500 -500
  77. package/src/services/wsdl/WsPackageProcess/v1.08/WsPackageProcess.ts +503 -0
  78. package/src/services/wsdl/WsResources/v1.01/WsResources.ts +119 -119
  79. package/src/services/wsdl/WsSMC/v1.24/WsSMC.ts +665 -665
  80. package/src/services/wsdl/WsSMC/v1.27/WsSMC.ts +591 -591
  81. package/src/services/wsdl/WsSMC/v1.28/WsSMC.ts +645 -645
  82. package/src/services/wsdl/WsSMC/v1.29/WsSMC.ts +660 -660
  83. package/src/services/wsdl/WsSasha/v1.01/WsSasha.ts +18 -18
  84. package/src/services/wsdl/WsTopology/v1.31/WsTopology.ts +856 -856
  85. package/src/services/wsdl/WsTopology/v1.32/WsTopology.ts +786 -786
  86. package/src/services/wsdl/WsTopology/v1.33/WsTopology.ts +835 -835
  87. package/src/services/wsdl/WsWorkunits/v1.88/WsWorkunits.ts +2944 -2944
  88. package/src/services/wsdl/WsWorkunits/v1.94/WsWorkunits.ts +3072 -3072
  89. package/src/services/wsdl/WsWorkunits/v1.95/WsWorkunits.ts +3073 -3073
  90. package/src/services/wsdl/WsWorkunits/v1.97/WsWorkunits.ts +3134 -3134
  91. package/src/services/wsdl/WsWorkunits/v1.98/WsWorkunits.ts +3182 -3182
  92. package/src/services/wsdl/WsWorkunits/v1.99/WsWorkunits.ts +3162 -3162
  93. package/src/services/wsdl/WsWorkunits/v2/WsWorkunits.ts +3153 -3153
  94. package/src/services/wsdl/WsWorkunits/v2.02/WsWorkunits.ts +3162 -3162
  95. package/src/services/wsdl/WsWorkunits/v2.03/WsWorkunits.ts +3164 -3164
  96. package/src/services/wsdl/WsWorkunits/v2.04/WsWorkunits.ts +3171 -3171
  97. package/src/services/wsdl/WsWorkunits/v2.05/WsWorkunits.ts +3177 -0
  98. package/src/services/wsdl/ws_access/v1.16/ws_access.ts +1086 -1086
  99. package/src/services/wsdl/ws_access/v1.17/ws_access.ts +1023 -1023
  100. package/src/services/wsdl/ws_account/v1.05/ws_account.ts +111 -111
  101. package/src/services/wsdl/ws_account/v1.06/ws_account.ts +109 -109
  102. package/src/services/wsdl/ws_account/v1.07/ws_account.ts +114 -114
  103. package/src/services/wsdl/ws_codesign/v1.1/ws_codesign.ts +95 -95
  104. package/src/services/wsdl/ws_elk/v1/ws_elk.ts +47 -47
  105. package/src/services/wsdl/ws_logaccess/v1/ws_logaccess.ts +83 -83
  106. package/src/services/wsdl/ws_logaccess/v1.02/ws_logaccess.ts +161 -161
  107. package/src/services/wsdl/ws_logaccess/v1.03/ws_logaccess.ts +190 -190
  108. package/src/services/wsdl/ws_logaccess/v1.04/ws_logaccess.ts +215 -215
  109. package/src/services/wsdl/ws_logaccess/v1.05/ws_logaccess.ts +219 -219
  110. package/src/services/wsdl/ws_logaccess/v1.08/ws_logaccess.ts +267 -267
  111. package/src/services/wsdl/ws_machine/v1.17/ws_machine.ts +567 -567
  112. package/src/services/wsdl/ws_machine/v1.18/ws_machine.ts +497 -497
  113. package/src/services/wsdl/ws_machine/v1.19/ws_machine.ts +497 -497
  114. package/src/services/wsdl/wsstore/v1.02/wsstore.ts +239 -239
  115. package/types/services/wsPackageProcess.d.ts +1 -1
  116. package/types/services/wsWorkunits.d.ts +1 -1
  117. package/types/services/wsdl/FileSpray/v1.27/FileSpray.d.ts +506 -506
  118. package/types/services/wsdl/WsCloud/v1.02/WsCloud.d.ts +18 -18
  119. package/types/services/wsdl/WsDFUXRef/v1.04/WsDFUXRef.d.ts +58 -57
  120. package/types/services/wsdl/WsDali/v1.07/WsDali.d.ts +42 -42
  121. package/types/services/wsdl/WsPackageProcess/{v1.07 → v1.08}/WsPackageProcess.d.ts +121 -118
  122. package/types/services/wsdl/WsSasha/v1.01/WsSasha.d.ts +13 -13
  123. package/types/services/wsdl/WsTopology/v1.33/WsTopology.d.ts +360 -360
  124. package/types/services/wsdl/WsWorkunits/v2.05/WsWorkunits.d.ts +2571 -0
  125. package/types/services/wsdl/ws_access/v1.17/ws_access.d.ts +268 -268
  126. package/types/services/wsdl/ws_account/v1.07/ws_account.d.ts +34 -34
  127. package/types/services/wsdl/ws_codesign/v1.1/ws_codesign.d.ts +22 -22
  128. package/types/services/wsdl/ws_elk/v1/ws_elk.d.ts +12 -12
  129. package/types/services/wsdl/wsstore/v1.02/wsstore.d.ts +61 -61
  130. package/types/services/wsdl/WsWorkunits/v2.04/WsWorkunits.d.ts +0 -2565
@@ -1,813 +1,813 @@
1
- // Ported from: https://github.com/hpcc-systems/HPCC-Platform/blob/f0ed9dbeca49c39fb55aa28fec295c89407ac663/esp/src/src/ESPGraph.ts
2
-
3
- export function safeAssign(obj: { [id: string]: any }, key: string, value: string) {
4
- if (key === "__proto__" || key === "constructor" || key === "prototype") return;
5
- obj[key] = value;
6
- }
7
-
8
- function xmlEncode(str: string): string {
9
- str = "" + str;
10
- return str.replace(/&/g, "&")
11
- .replace(/"/g, """)
12
- .replace(/'/g, "'")
13
- .replace(/</g, "&lt;")
14
- .replace(/>/g, "&gt;")
15
- .replace(/\n/g, "&#10;")
16
- .replace(/\r/g, "&#13;")
17
- ;
18
- }
19
-
20
- function espTime2Seconds(duration?: string): number {
21
- if (!duration) {
22
- return 0;
23
- } else if (!isNaN(+duration)) {
24
- return parseFloat(duration);
25
- }
26
- const re = /(?:(?:(\d+).days.)?(?:(\d+)h)?(?:(\d+)m)?(?:(\d+\.\d+|\d+)s))|(?:(\d+\.\d+|\d+)ms|(\d+\.\d+|\d+)us|(\d+\.\d+|\d+)ns)/;
27
- const match = re.exec(duration);
28
- if (!match) return 0;
29
- const days = +match[1] || 0;
30
- const hours = +match[2] || 0;
31
- const mins = +match[3] || 0;
32
- const secs = +match[4] || 0;
33
- const ms = +match[5] || 0;
34
- const us = +match[6] || 0;
35
- const ns = +match[7] || 0;
36
- return (days * 24 * 60 * 60) + (hours * 60 * 60) + (mins * 60) + secs + ms / 1000 + us / 1000000 + ns / 1000000000;
37
- }
38
-
39
- function unitTest(size: string, unit: string) {
40
- const nsIndex = size.indexOf(unit);
41
- if (nsIndex !== -1) {
42
- return parseFloat(size.substring(0, nsIndex));
43
- }
44
- return -1;
45
- }
46
-
47
- function espSize2Bytes(size: string): number {
48
- if (!size) {
49
- return 0;
50
- } else if (!isNaN(+size)) {
51
- return parseFloat(size);
52
- }
53
- let retVal = unitTest(size, "Kb");
54
- if (retVal >= 0) {
55
- return retVal * 1024;
56
- }
57
- retVal = unitTest(size, "Mb");
58
- if (retVal >= 0) {
59
- return retVal * Math.pow(1024, 2);
60
- }
61
- retVal = unitTest(size, "Gb");
62
- if (retVal >= 0) {
63
- return retVal * Math.pow(1024, 3);
64
- }
65
- retVal = unitTest(size, "Tb");
66
- if (retVal >= 0) {
67
- return retVal * Math.pow(1024, 4);
68
- }
69
- retVal = unitTest(size, "Pb");
70
- if (retVal >= 0) {
71
- return retVal * Math.pow(1024, 5);
72
- }
73
- retVal = unitTest(size, "Eb");
74
- if (retVal >= 0) {
75
- return retVal * Math.pow(1024, 6);
76
- }
77
- retVal = unitTest(size, "Zb");
78
- if (retVal >= 0) {
79
- return retVal * Math.pow(1024, 7);
80
- }
81
- retVal = unitTest(size, "b");
82
- if (retVal >= 0) {
83
- return retVal;
84
- }
85
- return 0;
86
- }
87
-
88
- function espSkew2Number(skew: string): number {
89
- if (!skew) {
90
- return 0;
91
- }
92
- return parseFloat(skew);
93
- }
94
-
95
- enum GRAPH_TYPE {
96
- UNKNOWN = 0,
97
- GRAPH = 1,
98
- SUBGRAPH = 2,
99
- VERTEX = 3,
100
- EDGE = 4,
101
- LAST = 5
102
- }
103
-
104
- enum GRAPH_TYPE_STRING {
105
- UNKNOWN = "Unknown",
106
- GRAPH = "Graph",
107
- SUBGRAPH = "Cluster",
108
- VERTEX = "Vertex",
109
- EDGE = "Edge",
110
- LAST = "Last"
111
- }
112
-
113
- class LocalisedXGMMLWriter {
114
-
115
- graph: QueryGraph;
116
- m_xgmml: string;
117
- m_visibleSubgraphs: { [id: string]: Subgraph };
118
- m_visibleVertices: { [id: string]: Vertex };
119
- m_semiVisibleVertices: { [id: string]: Vertex };
120
- m_visibleEdges: { [id: string]: Edge };
121
- noSpills: boolean;
122
-
123
- constructor(graph: QueryGraph) {
124
- this.graph = graph;
125
-
126
- this.m_xgmml = "";
127
- this.m_visibleSubgraphs = {};
128
- this.m_visibleVertices = {};
129
- this.m_semiVisibleVertices = {};
130
- this.m_visibleEdges = {};
131
- }
132
-
133
- calcVisibility(items: GraphItem[], localisationDepth: number, localisationDistance: number, noSpills: boolean): void {
134
- this.noSpills = noSpills;
135
- items.forEach((item) => {
136
- if (this.graph.isVertex(item)) {
137
- this.calcInVertexVisibility(item, localisationDistance);
138
- this.calcOutVertexVisibility(item, localisationDistance);
139
- } else if (this.graph.isEdge(item)) {
140
- this.calcInVertexVisibility(item.getSource(), localisationDistance - 1);
141
- this.calcOutVertexVisibility(item.getTarget(), localisationDistance - 1);
142
- } else if (this.graph.isSubgraph(item)) {
143
- this.m_visibleSubgraphs[item.__hpcc_id] = item;
144
- this.calcSubgraphVisibility(item, localisationDepth - 1);
145
- }
146
- });
147
- this.calcVisibility2();
148
- }
149
-
150
- calcInVertexVisibility(vertex: Vertex, localisationDistance: number) {
151
- if (this.noSpills && vertex.isSpill()) {
152
- localisationDistance++;
153
- }
154
- this.m_visibleVertices[vertex.__hpcc_id] = vertex;
155
- if (localisationDistance > 0) {
156
- vertex.getInEdges().forEach(edge => {
157
- this.calcInVertexVisibility(edge.getSource(), localisationDistance - 1);
158
- });
159
- }
160
- }
161
-
162
- calcOutVertexVisibility(vertex: Vertex, localisationDistance: number): void {
163
- if (this.noSpills && vertex.isSpill()) {
164
- localisationDistance++;
165
- }
166
- this.m_visibleVertices[vertex.__hpcc_id] = vertex;
167
- if (localisationDistance > 0) {
168
- vertex.getOutEdges().forEach(edge => {
169
- this.calcOutVertexVisibility(edge.getTarget(), localisationDistance - 1);
170
- });
171
- }
172
- }
173
-
174
- calcSubgraphVisibility(subgraph: Subgraph, localisationDepth: number): void {
175
- if (localisationDepth < 0) {
176
- return;
177
- }
178
-
179
- if (localisationDepth > 0) {
180
- subgraph.__hpcc_subgraphs.forEach((subgraph, idx) => {
181
- this.calcSubgraphVisibility(subgraph, localisationDepth - 1);
182
- });
183
- }
184
-
185
- subgraph.__hpcc_subgraphs.forEach((subgraph, idx) => {
186
- this.m_visibleSubgraphs[subgraph.__hpcc_id] = subgraph;
187
- });
188
- subgraph.__hpcc_vertices.forEach((vertex, idx) => {
189
- this.m_visibleVertices[vertex.__hpcc_id] = vertex;
190
- });
191
-
192
- // Calculate edges that pass through the subgraph ---
193
- const dedupEdges = {};
194
- this.graph.edges.forEach((edge: Edge, idx: any) => {
195
- if (edge.getSource().__hpcc_parent !== edge.getTarget().__hpcc_parent && subgraph === this.getCommonAncestor(edge)) {
196
- // Only include one unique edge between subgraphs ---
197
- if (!dedupEdges[edge.getSource().__hpcc_parent.__hpcc_id + "::" + edge.getTarget().__hpcc_parent.__hpcc_id]) {
198
- dedupEdges[edge.getSource().__hpcc_parent.__hpcc_id + "::" + edge.getTarget().__hpcc_parent.__hpcc_id] = true;
199
- this.m_visibleEdges[edge.__hpcc_id] = edge;
200
- }
201
- }
202
- });
203
- }
204
-
205
- buildVertexString(vertex: Vertex, isPoint: boolean): string {
206
- let attrStr = "";
207
- let propsStr = "";
208
- const props = vertex.getProperties();
209
- for (const key in props) {
210
- if (isPoint && key.indexOf("_kind") >= 0) {
211
- propsStr += "<att name=\"_kind\" value=\"point\"/>";
212
- } else if (key === "id" || key === "label") {
213
- attrStr += " " + key + "=\"" + xmlEncode(props[key]) + "\"";
214
- } else {
215
- propsStr += "<att name=\"" + key + "\" value=\"" + xmlEncode(props[key]) + "\"/>";
216
- }
217
- }
218
- return "<node" + attrStr + ">" + propsStr + "</node>";
219
- }
220
-
221
- buildEdgeString(edge: Edge): string {
222
- let attrStr: string = "";
223
- let propsStr: string = "";
224
- const props = edge.getProperties();
225
- for (const key in props) {
226
- if (key.toLowerCase() === "id" ||
227
- key.toLowerCase() === "label" ||
228
- key.toLowerCase() === "source" ||
229
- key.toLowerCase() === "target") {
230
- attrStr += " " + key + "=\"" + xmlEncode(props[key]) + "\"";
231
- } else {
232
- propsStr += "<att name=\"" + key + "\" value=\"" + xmlEncode(props[key]) + "\"/>";
233
- }
234
- }
235
- return "<edge" + attrStr + ">" + propsStr + "</edge>";
236
- }
237
-
238
- getAncestors(v: Vertex, ancestors: Subgraph[]): void {
239
- let parent = v.__hpcc_parent;
240
- while (parent) {
241
- ancestors.push(parent);
242
- parent = parent.__hpcc_parent;
243
- }
244
- }
245
-
246
- getCommonAncestorV(v1: Vertex, v2: Vertex): Subgraph | null {
247
- const v1_ancestors = [];
248
- const v2_ancestors = [];
249
- this.getAncestors(v1, v1_ancestors);
250
- this.getAncestors(v2, v2_ancestors);
251
- let finger1 = v1_ancestors.length - 1;
252
- let finger2 = v2_ancestors.length - 1;
253
- let retVal = null;
254
- while (finger1 >= 0 && finger2 >= 0 && v1_ancestors[finger1] === v2_ancestors[finger2]) {
255
- retVal = v1_ancestors[finger1];
256
- --finger1;
257
- --finger2;
258
- }
259
- return retVal;
260
- }
261
-
262
- getCommonAncestor(e: Edge): Subgraph | null {
263
- return this.getCommonAncestorV(e.getSource(), e.getTarget());
264
- }
265
-
266
- calcAncestorVisibility(vertex: Vertex): void {
267
- const ancestors = [];
268
- this.getAncestors(vertex, ancestors);
269
- ancestors.forEach((item, idx) => {
270
- this.m_visibleSubgraphs[item.__hpcc_id] = item;
271
- });
272
- }
273
-
274
- calcVisibility2(): void {
275
- for (const key in this.m_visibleVertices) {
276
- const vertex = this.m_visibleVertices[key];
277
- vertex.getInEdges().forEach((edge: Edge, idx: any) => {
278
- this.m_visibleEdges[edge.__hpcc_id] = edge;
279
- });
280
- vertex.getOutEdges().forEach((edge: Edge, idx: any) => {
281
- this.m_visibleEdges[edge.__hpcc_id] = edge;
282
- });
283
- this.calcAncestorVisibility(vertex);
284
- }
285
- this.calcSemiVisibleVertices();
286
- }
287
-
288
- addSemiVisibleEdge(edge: Edge): void {
289
- if (edge && !this.m_visibleEdges[edge.__hpcc_id]) {
290
- this.m_visibleEdges[edge.__hpcc_id] = edge;
291
- }
292
- }
293
-
294
- addSemiVisibleVertex(vertex: Vertex): void {
295
- if (!this.m_visibleVertices[vertex.__hpcc_id]) {
296
- this.m_semiVisibleVertices[vertex.__hpcc_id] = vertex;
297
- this.calcAncestorVisibility(vertex);
298
- }
299
- }
300
-
301
- calcSemiVisibleVertices(): void {
302
- for (const key in this.m_visibleEdges) {
303
- const edge = this.m_visibleEdges[key];
304
- let source = edge.getSource();
305
- this.addSemiVisibleVertex(source);
306
- while (this.noSpills && source.isSpill()) {
307
- const inEdges = source.getInEdges();
308
- if (inEdges.length) {
309
- this.addSemiVisibleEdge(inEdges[0]);
310
- source = inEdges[0].getSource();
311
- this.addSemiVisibleVertex(source);
312
- } else {
313
- break;
314
- }
315
- }
316
- let target = edge.getTarget();
317
- this.addSemiVisibleVertex(target);
318
- while (this.noSpills && target.isSpill()) {
319
- const outEdges = target.getOutEdges();
320
- if (outEdges.length) {
321
- this.addSemiVisibleEdge(outEdges[0]);
322
- target = outEdges[0].getTarget();
323
- this.addSemiVisibleVertex(target);
324
- } else {
325
- break;
326
- }
327
- }
328
- }
329
- }
330
-
331
- writeXgmml(): void {
332
- this.subgraphVisited(this.graph.subgraphs[0], true);
333
- this.graph.edges.forEach((edge: any, idx: any) => {
334
- this.edgeVisited(edge);
335
- });
336
- }
337
-
338
- subgraphVisited(subgraph: Subgraph, root: boolean = false): boolean {
339
- if (this.m_visibleSubgraphs[subgraph.__hpcc_id]) {
340
- let propsStr = "";
341
- this.m_xgmml += root ? "" : "<node id=\"" + subgraph.__hpcc_id + "\"><att><graph>";
342
- const xgmmlLen = this.m_xgmml.length;
343
- subgraph.walkSubgraphs(this);
344
- subgraph.walkVertices(this);
345
- if (xgmmlLen === this.m_xgmml.length) {
346
- // Add at least one child otherwise subgraphs will render as a vertex ---
347
- const vertex = subgraph.__hpcc_vertices[0];
348
- if (vertex) {
349
- this.m_xgmml += this.buildVertexString(vertex, true);
350
- }
351
- }
352
-
353
- const props = subgraph.getProperties();
354
- for (const key in props) {
355
- propsStr += "<att name=\"" + key + "\" value=\"" + xmlEncode(props[key]) + "\"/>";
356
- }
357
- this.m_xgmml += root ? "" : "</graph></att>" + propsStr + "</node>";
358
- }
359
- return false;
360
- }
361
-
362
- vertexVisited(vertex: Vertex) {
363
- if (this.m_visibleVertices[vertex.__hpcc_id]) {
364
- this.m_xgmml += this.buildVertexString(vertex, false);
365
- } else if (this.m_semiVisibleVertices[vertex.__hpcc_id]) {
366
- this.m_xgmml += this.buildVertexString(vertex, true);
367
- }
368
- }
369
-
370
- edgeVisited(edge: Edge) {
371
- if (this.m_visibleEdges[edge.__hpcc_id]) {
372
- this.m_xgmml += this.buildEdgeString(edge);
373
- }
374
- }
375
- }
376
-
377
- abstract class GraphItem {
378
-
379
- abstract _globalType: "Graph" | "Cluster" | "Vertex" | "Edge";
380
-
381
- __hpcc_graph: QueryGraph;
382
- __hpcc_parent: Subgraph;
383
- __widget: any;
384
-
385
- __hpcc_id: string;
386
- _globalID: string;
387
-
388
- constructor(graph: QueryGraph, id: string) {
389
- this.__hpcc_graph = graph;
390
- this.__hpcc_id = id;
391
- this._globalID = id;
392
- }
393
-
394
- getProperties() {
395
- const retVal: { [id: string]: any } = {};
396
- for (const key in this) {
397
- if (key.indexOf("__") !== 0 && this.hasOwnProperty(key)) {
398
- retVal[key] = this[key];
399
- }
400
- }
401
- return retVal;
402
- }
403
- }
404
-
405
- class Subgraph extends GraphItem {
406
- _globalType: "Graph" | "Cluster" | "Vertex" | "Edge";
407
-
408
- __hpcc_subgraphs: any[];
409
- __hpcc_vertices: any[];
410
- __hpcc_edges: any[];
411
- id: string;
412
-
413
- constructor(graph: QueryGraph, id: string) {
414
- super(graph, id);
415
- this._globalType = id === "0" ? "Graph" : "Cluster";
416
- this.__hpcc_subgraphs = [];
417
- this.__hpcc_vertices = [];
418
- this.__hpcc_edges = [];
419
- this.id = id;
420
- }
421
-
422
- addSubgraph(subgraph) {
423
- subgraph.__hpcc_parent = this;
424
- if (!this.__hpcc_subgraphs.some(subgraph2 => subgraph === subgraph2)) {
425
- this.__hpcc_subgraphs.push(subgraph);
426
- }
427
- }
428
-
429
- addVertex(vertex) {
430
- vertex.__hpcc_parent = this;
431
- if (!this.__hpcc_vertices.some(vertex2 => vertex === vertex2)) {
432
- this.__hpcc_vertices.push(vertex);
433
- }
434
- }
435
-
436
- removeVertex(vertex: any) {
437
- this.__hpcc_vertices = this.__hpcc_vertices.filter(vertex2 => vertex !== vertex2);
438
- }
439
-
440
- addEdge(edge) {
441
- edge.__hpcc_parent = this;
442
- if (!this.__hpcc_edges.some(edge2 => edge === edge2)) {
443
- this.__hpcc_edges.push(edge);
444
- }
445
- }
446
-
447
- removeEdge(edge: any) {
448
- this.__hpcc_edges = this.__hpcc_edges.filter(edge2 => edge !== edge2);
449
- }
450
-
451
- remove() {
452
- this.__hpcc_subgraphs.forEach(subgraph => subgraph.__hpcc_parent = this.__hpcc_parent);
453
- this.__hpcc_vertices.forEach(vertex => vertex.__hpcc_parent = this.__hpcc_parent);
454
- this.__hpcc_edges.forEach(edge => edge.__hpcc_parent = this.__hpcc_parent);
455
- delete this.__hpcc_parent;
456
- this.__hpcc_graph.removeItem(this);
457
- }
458
-
459
- walkSubgraphs(visitor: { subgraphVisited: (arg0: Subgraph) => boolean; }) {
460
- this.__hpcc_subgraphs.forEach((subgraph, idx) => {
461
- if (visitor.subgraphVisited(subgraph)) {
462
- subgraph.walkSubgraphs(visitor);
463
- }
464
- });
465
- }
466
-
467
- walkVertices(visitor: { vertexVisited: (arg0: Vertex) => void; }) {
468
- this.__hpcc_vertices.forEach((vertex, idx) => {
469
- visitor.vertexVisited(vertex);
470
- });
471
- }
472
- }
473
-
474
- class Vertex extends GraphItem {
475
- _globalType: "Graph" | "Cluster" | "Vertex" | "Edge" = "Vertex";
476
- _isSpill: boolean;
477
-
478
- constructor(graph: QueryGraph, id: string) {
479
- super(graph, id);
480
- }
481
-
482
- isSpill() {
483
- return this._isSpill;
484
- }
485
-
486
- remove() {
487
- const inVertices = this.getInVertices();
488
- if (inVertices.length <= 1) {
489
- console.warn(this.__hpcc_id + ": remove only supports single or zero inputs activities...");
490
- }
491
- this.getInEdges().forEach((edge: Edge) => {
492
- edge.remove();
493
- });
494
- this.getOutEdges().forEach((edge: Edge) => {
495
- edge.setSource(inVertices[0]);
496
- });
497
- this.__hpcc_parent?.removeVertex(this);
498
- this.__hpcc_graph.removeItem(this);
499
- }
500
-
501
- getInVertices(): Vertex[] {
502
- return this.getInEdges().map((edge) => {
503
- return edge.getSource();
504
- });
505
- }
506
-
507
- getInEdges(): Edge[] {
508
- return this.__hpcc_graph.edges.filter((edge) => {
509
- return edge.getTarget() === this;
510
- });
511
- }
512
-
513
- getOutVertices(): Vertex[] {
514
- return this.getOutEdges().map((edge) => {
515
- return edge.getTarget();
516
- });
517
- }
518
-
519
- getOutEdges(): Edge[] {
520
- return this.__hpcc_graph.edges.filter((edge) => {
521
- return edge.getSource() === this;
522
- });
523
- }
524
- }
525
-
526
- class Edge extends GraphItem {
527
- _globalType: "Graph" | "Cluster" | "Vertex" | "Edge" = "Edge";
528
-
529
- _sourceActivity: any;
530
- source: any;
531
- _targetActivity: any;
532
- target: any;
533
-
534
- constructor(graph: QueryGraph, id: string) {
535
- super(graph, id);
536
- this._globalType = "Edge";
537
- }
538
-
539
- remove() {
540
- this.__hpcc_graph.subgraphs.forEach((subgraph) => {
541
- subgraph.removeEdge(this);
542
- });
543
- this.__hpcc_graph.removeItem(this);
544
- }
545
-
546
- getSource(): Vertex {
547
- return this.__hpcc_graph.idx[this._sourceActivity || this.source] as Vertex;
548
- }
549
-
550
- setSource(source: Vertex) {
551
- if (this._sourceActivity) {
552
- this._sourceActivity = source.__hpcc_id;
553
- } else if (this.source) {
554
- this.source = source.__hpcc_id;
555
- }
556
- if (this.__widget) {
557
- this.__widget.setSource(this.getSource().__widget);
558
- }
559
- }
560
-
561
- getTarget(): Vertex {
562
- return this.__hpcc_graph.idx[this._targetActivity || this.target] as Vertex;
563
- }
564
- }
565
-
566
- export class QueryGraph {
567
- idx: { [id: string]: Subgraph | Vertex | Edge } = {};
568
- subgraphs: Subgraph[] = [];
569
- vertices: Vertex[] = [];
570
- edges: Edge[] = [];
571
-
572
- xgmml: string = "";
573
-
574
- constructor() {
575
- this.clear();
576
- }
577
-
578
- clear() {
579
- this.xgmml = "";
580
-
581
- this.idx = {};
582
- this.subgraphs = [];
583
- this.vertices = [];
584
- this.edges = [];
585
- }
586
-
587
- load(xgmml: string) {
588
- this.clear();
589
- this.merge(xgmml);
590
- }
591
-
592
- merge(xgmml: string) {
593
- this.xgmml = xgmml;
594
- const parser = new DOMParser();
595
- const dom = parser.parseFromString(xgmml, "text/xml");
596
- this.walkDocument(dom.documentElement, "0");
597
- }
598
-
599
- isSubgraph(item: GraphItem): item is Subgraph {
600
- return item instanceof Subgraph;
601
- }
602
-
603
- isVertex(item: GraphItem): item is Vertex {
604
- return item instanceof Vertex;
605
- }
606
-
607
- isEdge(item: GraphItem): item is Edge {
608
- return item instanceof Edge;
609
- }
610
-
611
- getGlobalType(item: QueryGraph | Subgraph | Vertex | Edge): GRAPH_TYPE {
612
- if (item instanceof Vertex) {
613
- return GRAPH_TYPE.VERTEX;
614
- } else if (item instanceof Edge) {
615
- return GRAPH_TYPE.EDGE;
616
- } else if (item instanceof Subgraph) {
617
- return GRAPH_TYPE.SUBGRAPH;
618
- } else if (item instanceof QueryGraph) {
619
- return GRAPH_TYPE.GRAPH;
620
- }
621
- return GRAPH_TYPE.UNKNOWN;
622
- }
623
-
624
- getGlobalTypeString(item: QueryGraph | Subgraph | Vertex | Edge): GRAPH_TYPE_STRING {
625
- if (item instanceof Vertex) {
626
- return GRAPH_TYPE_STRING.VERTEX;
627
- } else if (item instanceof Edge) {
628
- return GRAPH_TYPE_STRING.EDGE;
629
- } else if (item instanceof Subgraph) {
630
- return GRAPH_TYPE_STRING.SUBGRAPH;
631
- } else if (item instanceof QueryGraph) {
632
- return GRAPH_TYPE_STRING.GRAPH;
633
- }
634
- return GRAPH_TYPE_STRING.UNKNOWN;
635
- }
636
-
637
- getItem(docNode: HTMLElement, id: string): Subgraph | Vertex | Edge {
638
- if (!this.idx[id]) {
639
- switch (docNode.tagName) {
640
- case "graph":
641
- const subgraph = new Subgraph(this, id);
642
- this.subgraphs.push(subgraph);
643
- this.idx[id] = subgraph;
644
- break;
645
- case "node":
646
- const vertex = new Vertex(this, id);
647
- this.vertices.push(vertex);
648
- this.idx[id] = vertex;
649
- break;
650
- case "edge":
651
- const edge = new Edge(this, id);
652
- this.edges.push(edge);
653
- this.idx[id] = edge;
654
- break;
655
- default:
656
- console.warn("Graph.getItem - Unknown Node Type!");
657
- break;
658
- }
659
- }
660
- const retVal = this.idx[id];
661
- Array.from(docNode.attributes).forEach(attr => {
662
- safeAssign(retVal, attr.name, attr.value);
663
- });
664
- return retVal;
665
- }
666
-
667
- removeItem(item: Subgraph | Vertex | Edge) {
668
- delete this.idx[item.__hpcc_id];
669
- if (item instanceof Subgraph) {
670
- this.subgraphs = this.subgraphs.filter((subgraph: Subgraph) => {
671
- return item !== subgraph;
672
- });
673
- } else if (item instanceof Vertex) {
674
- this.vertices = this.vertices.filter(vertex => {
675
- return item !== vertex;
676
- });
677
- } else if (item instanceof Edge) {
678
- this.edges = this.edges.filter((edge: Edge) => {
679
- return item !== edge;
680
- });
681
- }
682
- }
683
-
684
- getChildByTagName(docNode: HTMLElement, tagName: string): HTMLElement | null {
685
- let retVal: HTMLElement | null = null;
686
- Array.from(docNode.childNodes as NodeListOf<HTMLElement>).some((childNode) => {
687
- if (childNode.tagName === tagName) {
688
- retVal = childNode;
689
- return true;
690
- }
691
- });
692
- return retVal;
693
- }
694
-
695
- walkDocument(docNode: HTMLElement, id: string): Subgraph | Vertex | Edge {
696
- const retVal: any = this.getItem(docNode, id);
697
- (docNode.childNodes as NodeListOf<HTMLElement>).forEach((childNode) => {
698
- switch (childNode.nodeType) {
699
- case 1: // ELEMENT_NODE
700
- switch (childNode.tagName) {
701
- case "graph":
702
- break;
703
- case "node":
704
- let isSubgraph = false;
705
- const attNode = this.getChildByTagName(childNode, "att");
706
- if (attNode) {
707
- const graphNode = this.getChildByTagName(attNode, "graph");
708
- if (graphNode) {
709
- isSubgraph = true;
710
- const subgraph = this.walkDocument(graphNode, childNode.getAttribute("id"));
711
- retVal.addSubgraph(subgraph);
712
- }
713
- }
714
- if (!isSubgraph) {
715
- const vertex = this.walkDocument(childNode, childNode.getAttribute("id"));
716
- retVal.addVertex(vertex);
717
- }
718
- break;
719
- case "att":
720
- const name = childNode.getAttribute("name");
721
- const uname = "_" + name;
722
- const value = childNode.getAttribute("value");
723
- if (name.indexOf("Time") === 0) {
724
- safeAssign(retVal, uname, value);
725
- safeAssign(retVal, name, "" + espTime2Seconds(value));
726
- } else if (name.indexOf("Size") === 0) {
727
- safeAssign(retVal, uname, value);
728
- safeAssign(retVal, name, "" + espSize2Bytes(value));
729
- } else if (name.indexOf("Skew") === 0) {
730
- safeAssign(retVal, uname, value);
731
- safeAssign(retVal, name, "" + espSkew2Number(value));
732
- } else {
733
- safeAssign(retVal, name, value);
734
- }
735
- break;
736
- case "edge":
737
- const edge: any = this.walkDocument(childNode, childNode.getAttribute("id"));
738
- if (edge.NumRowsProcessed !== undefined) {
739
- edge._eclwatchCount = edge.NumRowsProcessed.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
740
- } else if (edge.Count !== undefined) {
741
- edge._eclwatchCount = edge.Count.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
742
- } else if (edge.count !== undefined) {
743
- edge._eclwatchCount = edge.count.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
744
- }
745
- if (edge.inputProgress) {
746
- edge._eclwatchInputProgress = "[" + edge.inputProgress.replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "]";
747
- }
748
- if (edge.SkewMaxRowsProcessed && edge.SkewMinRowsProcessed) {
749
- edge._eclwatchSkew = "+" + edge.SkewMaxRowsProcessed + ", " + edge.SkewMinRowsProcessed;
750
- }
751
- if (edge._dependsOn) {
752
- } else if (edge._childGraph) {
753
- } else if (edge._sourceActivity || edge._targetActivity) {
754
- edge._isSpill = true;
755
- const source = edge.getSource();
756
- if (source) {
757
- source._isSpill = true;
758
- }
759
- const target = edge.getTarget();
760
- if (target) {
761
- target._isSpill = true;
762
- }
763
- }
764
- retVal.addEdge(edge);
765
- break;
766
- default:
767
- break;
768
- }
769
- break;
770
- case 2: // ATTRIBUTE_NODE
771
- case 3: // TEXT_NODE
772
- case 4: // CDATA_SECTION_NODE
773
- case 5: // ENTITY_REFERENCE_NODE
774
- case 6: // ENTITY_NODE
775
- case 7: // PROCESSING_INSTRUCTION_NODE
776
- case 8: // COMMENT_NODE
777
- case 9: // DOCUMENT_NODE
778
- case 10: // DOCUMENT_TYPE_NODE
779
- case 11: // DOCUMENT_FRAGMENT_NODE
780
- case 12: // NOTATION_NODE
781
- break;
782
- default:
783
- break;
784
- }
785
- });
786
- return retVal;
787
- }
788
-
789
- removeSubgraphs(): void {
790
- const subgraphs = [...this.subgraphs];
791
- subgraphs.forEach((subgraph) => {
792
- if (subgraph.__hpcc_parent instanceof Subgraph) {
793
- subgraph.remove();
794
- }
795
- });
796
- }
797
-
798
- removeSpillVertices(): void {
799
- const vertices = [...this.vertices];
800
- vertices.forEach((vertex) => {
801
- if (vertex.isSpill()) {
802
- vertex.remove();
803
- }
804
- });
805
- }
806
-
807
- getLocalisedXGMML(items: GraphItem[], localisationDepth: number, localisationDistance: number, noSpills: boolean): string {
808
- const xgmmlWriter = new LocalisedXGMMLWriter(this);
809
- xgmmlWriter.calcVisibility(items, localisationDepth, localisationDistance, noSpills);
810
- xgmmlWriter.writeXgmml();
811
- return "<graph>" + xgmmlWriter.m_xgmml + "</graph>";
812
- }
813
- }
1
+ // Ported from: https://github.com/hpcc-systems/HPCC-Platform/blob/f0ed9dbeca49c39fb55aa28fec295c89407ac663/esp/src/src/ESPGraph.ts
2
+
3
+ export function safeAssign(obj: { [id: string]: any }, key: string, value: string) {
4
+ if (key === "__proto__" || key === "constructor" || key === "prototype") return;
5
+ obj[key] = value;
6
+ }
7
+
8
+ function xmlEncode(str: string): string {
9
+ str = "" + str;
10
+ return str.replace(/&/g, "&amp;")
11
+ .replace(/"/g, "&quot;")
12
+ .replace(/'/g, "&apos;")
13
+ .replace(/</g, "&lt;")
14
+ .replace(/>/g, "&gt;")
15
+ .replace(/\n/g, "&#10;")
16
+ .replace(/\r/g, "&#13;")
17
+ ;
18
+ }
19
+
20
+ function espTime2Seconds(duration?: string): number {
21
+ if (!duration) {
22
+ return 0;
23
+ } else if (!isNaN(+duration)) {
24
+ return parseFloat(duration);
25
+ }
26
+ const re = /(?:(?:(\d+).days.)?(?:(\d+)h)?(?:(\d+)m)?(?:(\d+\.\d+|\d+)s))|(?:(\d+\.\d+|\d+)ms|(\d+\.\d+|\d+)us|(\d+\.\d+|\d+)ns)/;
27
+ const match = re.exec(duration);
28
+ if (!match) return 0;
29
+ const days = +match[1] || 0;
30
+ const hours = +match[2] || 0;
31
+ const mins = +match[3] || 0;
32
+ const secs = +match[4] || 0;
33
+ const ms = +match[5] || 0;
34
+ const us = +match[6] || 0;
35
+ const ns = +match[7] || 0;
36
+ return (days * 24 * 60 * 60) + (hours * 60 * 60) + (mins * 60) + secs + ms / 1000 + us / 1000000 + ns / 1000000000;
37
+ }
38
+
39
+ function unitTest(size: string, unit: string) {
40
+ const nsIndex = size.indexOf(unit);
41
+ if (nsIndex !== -1) {
42
+ return parseFloat(size.substring(0, nsIndex));
43
+ }
44
+ return -1;
45
+ }
46
+
47
+ function espSize2Bytes(size: string): number {
48
+ if (!size) {
49
+ return 0;
50
+ } else if (!isNaN(+size)) {
51
+ return parseFloat(size);
52
+ }
53
+ let retVal = unitTest(size, "Kb");
54
+ if (retVal >= 0) {
55
+ return retVal * 1024;
56
+ }
57
+ retVal = unitTest(size, "Mb");
58
+ if (retVal >= 0) {
59
+ return retVal * Math.pow(1024, 2);
60
+ }
61
+ retVal = unitTest(size, "Gb");
62
+ if (retVal >= 0) {
63
+ return retVal * Math.pow(1024, 3);
64
+ }
65
+ retVal = unitTest(size, "Tb");
66
+ if (retVal >= 0) {
67
+ return retVal * Math.pow(1024, 4);
68
+ }
69
+ retVal = unitTest(size, "Pb");
70
+ if (retVal >= 0) {
71
+ return retVal * Math.pow(1024, 5);
72
+ }
73
+ retVal = unitTest(size, "Eb");
74
+ if (retVal >= 0) {
75
+ return retVal * Math.pow(1024, 6);
76
+ }
77
+ retVal = unitTest(size, "Zb");
78
+ if (retVal >= 0) {
79
+ return retVal * Math.pow(1024, 7);
80
+ }
81
+ retVal = unitTest(size, "b");
82
+ if (retVal >= 0) {
83
+ return retVal;
84
+ }
85
+ return 0;
86
+ }
87
+
88
+ function espSkew2Number(skew: string): number {
89
+ if (!skew) {
90
+ return 0;
91
+ }
92
+ return parseFloat(skew);
93
+ }
94
+
95
+ enum GRAPH_TYPE {
96
+ UNKNOWN = 0,
97
+ GRAPH = 1,
98
+ SUBGRAPH = 2,
99
+ VERTEX = 3,
100
+ EDGE = 4,
101
+ LAST = 5
102
+ }
103
+
104
+ enum GRAPH_TYPE_STRING {
105
+ UNKNOWN = "Unknown",
106
+ GRAPH = "Graph",
107
+ SUBGRAPH = "Cluster",
108
+ VERTEX = "Vertex",
109
+ EDGE = "Edge",
110
+ LAST = "Last"
111
+ }
112
+
113
+ class LocalisedXGMMLWriter {
114
+
115
+ graph: QueryGraph;
116
+ m_xgmml: string;
117
+ m_visibleSubgraphs: { [id: string]: Subgraph };
118
+ m_visibleVertices: { [id: string]: Vertex };
119
+ m_semiVisibleVertices: { [id: string]: Vertex };
120
+ m_visibleEdges: { [id: string]: Edge };
121
+ noSpills: boolean;
122
+
123
+ constructor(graph: QueryGraph) {
124
+ this.graph = graph;
125
+
126
+ this.m_xgmml = "";
127
+ this.m_visibleSubgraphs = {};
128
+ this.m_visibleVertices = {};
129
+ this.m_semiVisibleVertices = {};
130
+ this.m_visibleEdges = {};
131
+ }
132
+
133
+ calcVisibility(items: GraphItem[], localisationDepth: number, localisationDistance: number, noSpills: boolean): void {
134
+ this.noSpills = noSpills;
135
+ items.forEach((item) => {
136
+ if (this.graph.isVertex(item)) {
137
+ this.calcInVertexVisibility(item, localisationDistance);
138
+ this.calcOutVertexVisibility(item, localisationDistance);
139
+ } else if (this.graph.isEdge(item)) {
140
+ this.calcInVertexVisibility(item.getSource(), localisationDistance - 1);
141
+ this.calcOutVertexVisibility(item.getTarget(), localisationDistance - 1);
142
+ } else if (this.graph.isSubgraph(item)) {
143
+ this.m_visibleSubgraphs[item.__hpcc_id] = item;
144
+ this.calcSubgraphVisibility(item, localisationDepth - 1);
145
+ }
146
+ });
147
+ this.calcVisibility2();
148
+ }
149
+
150
+ calcInVertexVisibility(vertex: Vertex, localisationDistance: number) {
151
+ if (this.noSpills && vertex.isSpill()) {
152
+ localisationDistance++;
153
+ }
154
+ this.m_visibleVertices[vertex.__hpcc_id] = vertex;
155
+ if (localisationDistance > 0) {
156
+ vertex.getInEdges().forEach(edge => {
157
+ this.calcInVertexVisibility(edge.getSource(), localisationDistance - 1);
158
+ });
159
+ }
160
+ }
161
+
162
+ calcOutVertexVisibility(vertex: Vertex, localisationDistance: number): void {
163
+ if (this.noSpills && vertex.isSpill()) {
164
+ localisationDistance++;
165
+ }
166
+ this.m_visibleVertices[vertex.__hpcc_id] = vertex;
167
+ if (localisationDistance > 0) {
168
+ vertex.getOutEdges().forEach(edge => {
169
+ this.calcOutVertexVisibility(edge.getTarget(), localisationDistance - 1);
170
+ });
171
+ }
172
+ }
173
+
174
+ calcSubgraphVisibility(subgraph: Subgraph, localisationDepth: number): void {
175
+ if (localisationDepth < 0) {
176
+ return;
177
+ }
178
+
179
+ if (localisationDepth > 0) {
180
+ subgraph.__hpcc_subgraphs.forEach((subgraph, idx) => {
181
+ this.calcSubgraphVisibility(subgraph, localisationDepth - 1);
182
+ });
183
+ }
184
+
185
+ subgraph.__hpcc_subgraphs.forEach((subgraph, idx) => {
186
+ this.m_visibleSubgraphs[subgraph.__hpcc_id] = subgraph;
187
+ });
188
+ subgraph.__hpcc_vertices.forEach((vertex, idx) => {
189
+ this.m_visibleVertices[vertex.__hpcc_id] = vertex;
190
+ });
191
+
192
+ // Calculate edges that pass through the subgraph ---
193
+ const dedupEdges = {};
194
+ this.graph.edges.forEach((edge: Edge, idx: any) => {
195
+ if (edge.getSource().__hpcc_parent !== edge.getTarget().__hpcc_parent && subgraph === this.getCommonAncestor(edge)) {
196
+ // Only include one unique edge between subgraphs ---
197
+ if (!dedupEdges[edge.getSource().__hpcc_parent.__hpcc_id + "::" + edge.getTarget().__hpcc_parent.__hpcc_id]) {
198
+ dedupEdges[edge.getSource().__hpcc_parent.__hpcc_id + "::" + edge.getTarget().__hpcc_parent.__hpcc_id] = true;
199
+ this.m_visibleEdges[edge.__hpcc_id] = edge;
200
+ }
201
+ }
202
+ });
203
+ }
204
+
205
+ buildVertexString(vertex: Vertex, isPoint: boolean): string {
206
+ let attrStr = "";
207
+ let propsStr = "";
208
+ const props = vertex.getProperties();
209
+ for (const key in props) {
210
+ if (isPoint && key.indexOf("_kind") >= 0) {
211
+ propsStr += "<att name=\"_kind\" value=\"point\"/>";
212
+ } else if (key === "id" || key === "label") {
213
+ attrStr += " " + key + "=\"" + xmlEncode(props[key]) + "\"";
214
+ } else {
215
+ propsStr += "<att name=\"" + key + "\" value=\"" + xmlEncode(props[key]) + "\"/>";
216
+ }
217
+ }
218
+ return "<node" + attrStr + ">" + propsStr + "</node>";
219
+ }
220
+
221
+ buildEdgeString(edge: Edge): string {
222
+ let attrStr: string = "";
223
+ let propsStr: string = "";
224
+ const props = edge.getProperties();
225
+ for (const key in props) {
226
+ if (key.toLowerCase() === "id" ||
227
+ key.toLowerCase() === "label" ||
228
+ key.toLowerCase() === "source" ||
229
+ key.toLowerCase() === "target") {
230
+ attrStr += " " + key + "=\"" + xmlEncode(props[key]) + "\"";
231
+ } else {
232
+ propsStr += "<att name=\"" + key + "\" value=\"" + xmlEncode(props[key]) + "\"/>";
233
+ }
234
+ }
235
+ return "<edge" + attrStr + ">" + propsStr + "</edge>";
236
+ }
237
+
238
+ getAncestors(v: Vertex, ancestors: Subgraph[]): void {
239
+ let parent = v.__hpcc_parent;
240
+ while (parent) {
241
+ ancestors.push(parent);
242
+ parent = parent.__hpcc_parent;
243
+ }
244
+ }
245
+
246
+ getCommonAncestorV(v1: Vertex, v2: Vertex): Subgraph | null {
247
+ const v1_ancestors = [];
248
+ const v2_ancestors = [];
249
+ this.getAncestors(v1, v1_ancestors);
250
+ this.getAncestors(v2, v2_ancestors);
251
+ let finger1 = v1_ancestors.length - 1;
252
+ let finger2 = v2_ancestors.length - 1;
253
+ let retVal = null;
254
+ while (finger1 >= 0 && finger2 >= 0 && v1_ancestors[finger1] === v2_ancestors[finger2]) {
255
+ retVal = v1_ancestors[finger1];
256
+ --finger1;
257
+ --finger2;
258
+ }
259
+ return retVal;
260
+ }
261
+
262
+ getCommonAncestor(e: Edge): Subgraph | null {
263
+ return this.getCommonAncestorV(e.getSource(), e.getTarget());
264
+ }
265
+
266
+ calcAncestorVisibility(vertex: Vertex): void {
267
+ const ancestors = [];
268
+ this.getAncestors(vertex, ancestors);
269
+ ancestors.forEach((item, idx) => {
270
+ this.m_visibleSubgraphs[item.__hpcc_id] = item;
271
+ });
272
+ }
273
+
274
+ calcVisibility2(): void {
275
+ for (const key in this.m_visibleVertices) {
276
+ const vertex = this.m_visibleVertices[key];
277
+ vertex.getInEdges().forEach((edge: Edge, idx: any) => {
278
+ this.m_visibleEdges[edge.__hpcc_id] = edge;
279
+ });
280
+ vertex.getOutEdges().forEach((edge: Edge, idx: any) => {
281
+ this.m_visibleEdges[edge.__hpcc_id] = edge;
282
+ });
283
+ this.calcAncestorVisibility(vertex);
284
+ }
285
+ this.calcSemiVisibleVertices();
286
+ }
287
+
288
+ addSemiVisibleEdge(edge: Edge): void {
289
+ if (edge && !this.m_visibleEdges[edge.__hpcc_id]) {
290
+ this.m_visibleEdges[edge.__hpcc_id] = edge;
291
+ }
292
+ }
293
+
294
+ addSemiVisibleVertex(vertex: Vertex): void {
295
+ if (!this.m_visibleVertices[vertex.__hpcc_id]) {
296
+ this.m_semiVisibleVertices[vertex.__hpcc_id] = vertex;
297
+ this.calcAncestorVisibility(vertex);
298
+ }
299
+ }
300
+
301
+ calcSemiVisibleVertices(): void {
302
+ for (const key in this.m_visibleEdges) {
303
+ const edge = this.m_visibleEdges[key];
304
+ let source = edge.getSource();
305
+ this.addSemiVisibleVertex(source);
306
+ while (this.noSpills && source.isSpill()) {
307
+ const inEdges = source.getInEdges();
308
+ if (inEdges.length) {
309
+ this.addSemiVisibleEdge(inEdges[0]);
310
+ source = inEdges[0].getSource();
311
+ this.addSemiVisibleVertex(source);
312
+ } else {
313
+ break;
314
+ }
315
+ }
316
+ let target = edge.getTarget();
317
+ this.addSemiVisibleVertex(target);
318
+ while (this.noSpills && target.isSpill()) {
319
+ const outEdges = target.getOutEdges();
320
+ if (outEdges.length) {
321
+ this.addSemiVisibleEdge(outEdges[0]);
322
+ target = outEdges[0].getTarget();
323
+ this.addSemiVisibleVertex(target);
324
+ } else {
325
+ break;
326
+ }
327
+ }
328
+ }
329
+ }
330
+
331
+ writeXgmml(): void {
332
+ this.subgraphVisited(this.graph.subgraphs[0], true);
333
+ this.graph.edges.forEach((edge: any, idx: any) => {
334
+ this.edgeVisited(edge);
335
+ });
336
+ }
337
+
338
+ subgraphVisited(subgraph: Subgraph, root: boolean = false): boolean {
339
+ if (this.m_visibleSubgraphs[subgraph.__hpcc_id]) {
340
+ let propsStr = "";
341
+ this.m_xgmml += root ? "" : "<node id=\"" + subgraph.__hpcc_id + "\"><att><graph>";
342
+ const xgmmlLen = this.m_xgmml.length;
343
+ subgraph.walkSubgraphs(this);
344
+ subgraph.walkVertices(this);
345
+ if (xgmmlLen === this.m_xgmml.length) {
346
+ // Add at least one child otherwise subgraphs will render as a vertex ---
347
+ const vertex = subgraph.__hpcc_vertices[0];
348
+ if (vertex) {
349
+ this.m_xgmml += this.buildVertexString(vertex, true);
350
+ }
351
+ }
352
+
353
+ const props = subgraph.getProperties();
354
+ for (const key in props) {
355
+ propsStr += "<att name=\"" + key + "\" value=\"" + xmlEncode(props[key]) + "\"/>";
356
+ }
357
+ this.m_xgmml += root ? "" : "</graph></att>" + propsStr + "</node>";
358
+ }
359
+ return false;
360
+ }
361
+
362
+ vertexVisited(vertex: Vertex) {
363
+ if (this.m_visibleVertices[vertex.__hpcc_id]) {
364
+ this.m_xgmml += this.buildVertexString(vertex, false);
365
+ } else if (this.m_semiVisibleVertices[vertex.__hpcc_id]) {
366
+ this.m_xgmml += this.buildVertexString(vertex, true);
367
+ }
368
+ }
369
+
370
+ edgeVisited(edge: Edge) {
371
+ if (this.m_visibleEdges[edge.__hpcc_id]) {
372
+ this.m_xgmml += this.buildEdgeString(edge);
373
+ }
374
+ }
375
+ }
376
+
377
+ abstract class GraphItem {
378
+
379
+ abstract _globalType: "Graph" | "Cluster" | "Vertex" | "Edge";
380
+
381
+ __hpcc_graph: QueryGraph;
382
+ __hpcc_parent: Subgraph;
383
+ __widget: any;
384
+
385
+ __hpcc_id: string;
386
+ _globalID: string;
387
+
388
+ constructor(graph: QueryGraph, id: string) {
389
+ this.__hpcc_graph = graph;
390
+ this.__hpcc_id = id;
391
+ this._globalID = id;
392
+ }
393
+
394
+ getProperties() {
395
+ const retVal: { [id: string]: any } = {};
396
+ for (const key in this) {
397
+ if (key.indexOf("__") !== 0 && this.hasOwnProperty(key)) {
398
+ retVal[key] = this[key];
399
+ }
400
+ }
401
+ return retVal;
402
+ }
403
+ }
404
+
405
+ class Subgraph extends GraphItem {
406
+ _globalType: "Graph" | "Cluster" | "Vertex" | "Edge";
407
+
408
+ __hpcc_subgraphs: any[];
409
+ __hpcc_vertices: any[];
410
+ __hpcc_edges: any[];
411
+ id: string;
412
+
413
+ constructor(graph: QueryGraph, id: string) {
414
+ super(graph, id);
415
+ this._globalType = id === "0" ? "Graph" : "Cluster";
416
+ this.__hpcc_subgraphs = [];
417
+ this.__hpcc_vertices = [];
418
+ this.__hpcc_edges = [];
419
+ this.id = id;
420
+ }
421
+
422
+ addSubgraph(subgraph) {
423
+ subgraph.__hpcc_parent = this;
424
+ if (!this.__hpcc_subgraphs.some(subgraph2 => subgraph === subgraph2)) {
425
+ this.__hpcc_subgraphs.push(subgraph);
426
+ }
427
+ }
428
+
429
+ addVertex(vertex) {
430
+ vertex.__hpcc_parent = this;
431
+ if (!this.__hpcc_vertices.some(vertex2 => vertex === vertex2)) {
432
+ this.__hpcc_vertices.push(vertex);
433
+ }
434
+ }
435
+
436
+ removeVertex(vertex: any) {
437
+ this.__hpcc_vertices = this.__hpcc_vertices.filter(vertex2 => vertex !== vertex2);
438
+ }
439
+
440
+ addEdge(edge) {
441
+ edge.__hpcc_parent = this;
442
+ if (!this.__hpcc_edges.some(edge2 => edge === edge2)) {
443
+ this.__hpcc_edges.push(edge);
444
+ }
445
+ }
446
+
447
+ removeEdge(edge: any) {
448
+ this.__hpcc_edges = this.__hpcc_edges.filter(edge2 => edge !== edge2);
449
+ }
450
+
451
+ remove() {
452
+ this.__hpcc_subgraphs.forEach(subgraph => subgraph.__hpcc_parent = this.__hpcc_parent);
453
+ this.__hpcc_vertices.forEach(vertex => vertex.__hpcc_parent = this.__hpcc_parent);
454
+ this.__hpcc_edges.forEach(edge => edge.__hpcc_parent = this.__hpcc_parent);
455
+ delete this.__hpcc_parent;
456
+ this.__hpcc_graph.removeItem(this);
457
+ }
458
+
459
+ walkSubgraphs(visitor: { subgraphVisited: (arg0: Subgraph) => boolean; }) {
460
+ this.__hpcc_subgraphs.forEach((subgraph, idx) => {
461
+ if (visitor.subgraphVisited(subgraph)) {
462
+ subgraph.walkSubgraphs(visitor);
463
+ }
464
+ });
465
+ }
466
+
467
+ walkVertices(visitor: { vertexVisited: (arg0: Vertex) => void; }) {
468
+ this.__hpcc_vertices.forEach((vertex, idx) => {
469
+ visitor.vertexVisited(vertex);
470
+ });
471
+ }
472
+ }
473
+
474
+ class Vertex extends GraphItem {
475
+ _globalType: "Graph" | "Cluster" | "Vertex" | "Edge" = "Vertex";
476
+ _isSpill: boolean;
477
+
478
+ constructor(graph: QueryGraph, id: string) {
479
+ super(graph, id);
480
+ }
481
+
482
+ isSpill() {
483
+ return this._isSpill;
484
+ }
485
+
486
+ remove() {
487
+ const inVertices = this.getInVertices();
488
+ if (inVertices.length <= 1) {
489
+ console.warn(this.__hpcc_id + ": remove only supports single or zero inputs activities...");
490
+ }
491
+ this.getInEdges().forEach((edge: Edge) => {
492
+ edge.remove();
493
+ });
494
+ this.getOutEdges().forEach((edge: Edge) => {
495
+ edge.setSource(inVertices[0]);
496
+ });
497
+ this.__hpcc_parent?.removeVertex(this);
498
+ this.__hpcc_graph.removeItem(this);
499
+ }
500
+
501
+ getInVertices(): Vertex[] {
502
+ return this.getInEdges().map((edge) => {
503
+ return edge.getSource();
504
+ });
505
+ }
506
+
507
+ getInEdges(): Edge[] {
508
+ return this.__hpcc_graph.edges.filter((edge) => {
509
+ return edge.getTarget() === this;
510
+ });
511
+ }
512
+
513
+ getOutVertices(): Vertex[] {
514
+ return this.getOutEdges().map((edge) => {
515
+ return edge.getTarget();
516
+ });
517
+ }
518
+
519
+ getOutEdges(): Edge[] {
520
+ return this.__hpcc_graph.edges.filter((edge) => {
521
+ return edge.getSource() === this;
522
+ });
523
+ }
524
+ }
525
+
526
+ class Edge extends GraphItem {
527
+ _globalType: "Graph" | "Cluster" | "Vertex" | "Edge" = "Edge";
528
+
529
+ _sourceActivity: any;
530
+ source: any;
531
+ _targetActivity: any;
532
+ target: any;
533
+
534
+ constructor(graph: QueryGraph, id: string) {
535
+ super(graph, id);
536
+ this._globalType = "Edge";
537
+ }
538
+
539
+ remove() {
540
+ this.__hpcc_graph.subgraphs.forEach((subgraph) => {
541
+ subgraph.removeEdge(this);
542
+ });
543
+ this.__hpcc_graph.removeItem(this);
544
+ }
545
+
546
+ getSource(): Vertex {
547
+ return this.__hpcc_graph.idx[this._sourceActivity || this.source] as Vertex;
548
+ }
549
+
550
+ setSource(source: Vertex) {
551
+ if (this._sourceActivity) {
552
+ this._sourceActivity = source.__hpcc_id;
553
+ } else if (this.source) {
554
+ this.source = source.__hpcc_id;
555
+ }
556
+ if (this.__widget) {
557
+ this.__widget.setSource(this.getSource().__widget);
558
+ }
559
+ }
560
+
561
+ getTarget(): Vertex {
562
+ return this.__hpcc_graph.idx[this._targetActivity || this.target] as Vertex;
563
+ }
564
+ }
565
+
566
+ export class QueryGraph {
567
+ idx: { [id: string]: Subgraph | Vertex | Edge } = {};
568
+ subgraphs: Subgraph[] = [];
569
+ vertices: Vertex[] = [];
570
+ edges: Edge[] = [];
571
+
572
+ xgmml: string = "";
573
+
574
+ constructor() {
575
+ this.clear();
576
+ }
577
+
578
+ clear() {
579
+ this.xgmml = "";
580
+
581
+ this.idx = {};
582
+ this.subgraphs = [];
583
+ this.vertices = [];
584
+ this.edges = [];
585
+ }
586
+
587
+ load(xgmml: string) {
588
+ this.clear();
589
+ this.merge(xgmml);
590
+ }
591
+
592
+ merge(xgmml: string) {
593
+ this.xgmml = xgmml;
594
+ const parser = new DOMParser();
595
+ const dom = parser.parseFromString(xgmml, "text/xml");
596
+ this.walkDocument(dom.documentElement, "0");
597
+ }
598
+
599
+ isSubgraph(item: GraphItem): item is Subgraph {
600
+ return item instanceof Subgraph;
601
+ }
602
+
603
+ isVertex(item: GraphItem): item is Vertex {
604
+ return item instanceof Vertex;
605
+ }
606
+
607
+ isEdge(item: GraphItem): item is Edge {
608
+ return item instanceof Edge;
609
+ }
610
+
611
+ getGlobalType(item: QueryGraph | Subgraph | Vertex | Edge): GRAPH_TYPE {
612
+ if (item instanceof Vertex) {
613
+ return GRAPH_TYPE.VERTEX;
614
+ } else if (item instanceof Edge) {
615
+ return GRAPH_TYPE.EDGE;
616
+ } else if (item instanceof Subgraph) {
617
+ return GRAPH_TYPE.SUBGRAPH;
618
+ } else if (item instanceof QueryGraph) {
619
+ return GRAPH_TYPE.GRAPH;
620
+ }
621
+ return GRAPH_TYPE.UNKNOWN;
622
+ }
623
+
624
+ getGlobalTypeString(item: QueryGraph | Subgraph | Vertex | Edge): GRAPH_TYPE_STRING {
625
+ if (item instanceof Vertex) {
626
+ return GRAPH_TYPE_STRING.VERTEX;
627
+ } else if (item instanceof Edge) {
628
+ return GRAPH_TYPE_STRING.EDGE;
629
+ } else if (item instanceof Subgraph) {
630
+ return GRAPH_TYPE_STRING.SUBGRAPH;
631
+ } else if (item instanceof QueryGraph) {
632
+ return GRAPH_TYPE_STRING.GRAPH;
633
+ }
634
+ return GRAPH_TYPE_STRING.UNKNOWN;
635
+ }
636
+
637
+ getItem(docNode: HTMLElement, id: string): Subgraph | Vertex | Edge {
638
+ if (!this.idx[id]) {
639
+ switch (docNode.tagName) {
640
+ case "graph":
641
+ const subgraph = new Subgraph(this, id);
642
+ this.subgraphs.push(subgraph);
643
+ this.idx[id] = subgraph;
644
+ break;
645
+ case "node":
646
+ const vertex = new Vertex(this, id);
647
+ this.vertices.push(vertex);
648
+ this.idx[id] = vertex;
649
+ break;
650
+ case "edge":
651
+ const edge = new Edge(this, id);
652
+ this.edges.push(edge);
653
+ this.idx[id] = edge;
654
+ break;
655
+ default:
656
+ console.warn("Graph.getItem - Unknown Node Type!");
657
+ break;
658
+ }
659
+ }
660
+ const retVal = this.idx[id];
661
+ Array.from(docNode.attributes).forEach(attr => {
662
+ safeAssign(retVal, attr.name, attr.value);
663
+ });
664
+ return retVal;
665
+ }
666
+
667
+ removeItem(item: Subgraph | Vertex | Edge) {
668
+ delete this.idx[item.__hpcc_id];
669
+ if (item instanceof Subgraph) {
670
+ this.subgraphs = this.subgraphs.filter((subgraph: Subgraph) => {
671
+ return item !== subgraph;
672
+ });
673
+ } else if (item instanceof Vertex) {
674
+ this.vertices = this.vertices.filter(vertex => {
675
+ return item !== vertex;
676
+ });
677
+ } else if (item instanceof Edge) {
678
+ this.edges = this.edges.filter((edge: Edge) => {
679
+ return item !== edge;
680
+ });
681
+ }
682
+ }
683
+
684
+ getChildByTagName(docNode: HTMLElement, tagName: string): HTMLElement | null {
685
+ let retVal: HTMLElement | null = null;
686
+ Array.from(docNode.childNodes as NodeListOf<HTMLElement>).some((childNode) => {
687
+ if (childNode.tagName === tagName) {
688
+ retVal = childNode;
689
+ return true;
690
+ }
691
+ });
692
+ return retVal;
693
+ }
694
+
695
+ walkDocument(docNode: HTMLElement, id: string): Subgraph | Vertex | Edge {
696
+ const retVal: any = this.getItem(docNode, id);
697
+ (docNode.childNodes as NodeListOf<HTMLElement>).forEach((childNode) => {
698
+ switch (childNode.nodeType) {
699
+ case 1: // ELEMENT_NODE
700
+ switch (childNode.tagName) {
701
+ case "graph":
702
+ break;
703
+ case "node":
704
+ let isSubgraph = false;
705
+ const attNode = this.getChildByTagName(childNode, "att");
706
+ if (attNode) {
707
+ const graphNode = this.getChildByTagName(attNode, "graph");
708
+ if (graphNode) {
709
+ isSubgraph = true;
710
+ const subgraph = this.walkDocument(graphNode, childNode.getAttribute("id"));
711
+ retVal.addSubgraph(subgraph);
712
+ }
713
+ }
714
+ if (!isSubgraph) {
715
+ const vertex = this.walkDocument(childNode, childNode.getAttribute("id"));
716
+ retVal.addVertex(vertex);
717
+ }
718
+ break;
719
+ case "att":
720
+ const name = childNode.getAttribute("name");
721
+ const uname = "_" + name;
722
+ const value = childNode.getAttribute("value");
723
+ if (name.indexOf("Time") === 0) {
724
+ safeAssign(retVal, uname, value);
725
+ safeAssign(retVal, name, "" + espTime2Seconds(value));
726
+ } else if (name.indexOf("Size") === 0) {
727
+ safeAssign(retVal, uname, value);
728
+ safeAssign(retVal, name, "" + espSize2Bytes(value));
729
+ } else if (name.indexOf("Skew") === 0) {
730
+ safeAssign(retVal, uname, value);
731
+ safeAssign(retVal, name, "" + espSkew2Number(value));
732
+ } else {
733
+ safeAssign(retVal, name, value);
734
+ }
735
+ break;
736
+ case "edge":
737
+ const edge: any = this.walkDocument(childNode, childNode.getAttribute("id"));
738
+ if (edge.NumRowsProcessed !== undefined) {
739
+ edge._eclwatchCount = edge.NumRowsProcessed.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
740
+ } else if (edge.Count !== undefined) {
741
+ edge._eclwatchCount = edge.Count.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
742
+ } else if (edge.count !== undefined) {
743
+ edge._eclwatchCount = edge.count.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
744
+ }
745
+ if (edge.inputProgress) {
746
+ edge._eclwatchInputProgress = "[" + edge.inputProgress.replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "]";
747
+ }
748
+ if (edge.SkewMaxRowsProcessed && edge.SkewMinRowsProcessed) {
749
+ edge._eclwatchSkew = "+" + edge.SkewMaxRowsProcessed + ", " + edge.SkewMinRowsProcessed;
750
+ }
751
+ if (edge._dependsOn) {
752
+ } else if (edge._childGraph) {
753
+ } else if (edge._sourceActivity || edge._targetActivity) {
754
+ edge._isSpill = true;
755
+ const source = edge.getSource();
756
+ if (source) {
757
+ source._isSpill = true;
758
+ }
759
+ const target = edge.getTarget();
760
+ if (target) {
761
+ target._isSpill = true;
762
+ }
763
+ }
764
+ retVal.addEdge(edge);
765
+ break;
766
+ default:
767
+ break;
768
+ }
769
+ break;
770
+ case 2: // ATTRIBUTE_NODE
771
+ case 3: // TEXT_NODE
772
+ case 4: // CDATA_SECTION_NODE
773
+ case 5: // ENTITY_REFERENCE_NODE
774
+ case 6: // ENTITY_NODE
775
+ case 7: // PROCESSING_INSTRUCTION_NODE
776
+ case 8: // COMMENT_NODE
777
+ case 9: // DOCUMENT_NODE
778
+ case 10: // DOCUMENT_TYPE_NODE
779
+ case 11: // DOCUMENT_FRAGMENT_NODE
780
+ case 12: // NOTATION_NODE
781
+ break;
782
+ default:
783
+ break;
784
+ }
785
+ });
786
+ return retVal;
787
+ }
788
+
789
+ removeSubgraphs(): void {
790
+ const subgraphs = [...this.subgraphs];
791
+ subgraphs.forEach((subgraph) => {
792
+ if (subgraph.__hpcc_parent instanceof Subgraph) {
793
+ subgraph.remove();
794
+ }
795
+ });
796
+ }
797
+
798
+ removeSpillVertices(): void {
799
+ const vertices = [...this.vertices];
800
+ vertices.forEach((vertex) => {
801
+ if (vertex.isSpill()) {
802
+ vertex.remove();
803
+ }
804
+ });
805
+ }
806
+
807
+ getLocalisedXGMML(items: GraphItem[], localisationDepth: number, localisationDistance: number, noSpills: boolean): string {
808
+ const xgmmlWriter = new LocalisedXGMMLWriter(this);
809
+ xgmmlWriter.calcVisibility(items, localisationDepth, localisationDistance, noSpills);
810
+ xgmmlWriter.writeXgmml();
811
+ return "<graph>" + xgmmlWriter.m_xgmml + "</graph>";
812
+ }
813
+ }