@hpcc-js/util 3.5.2 → 3.5.4
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.
- package/LICENSE +43 -43
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +1 -1
- package/dist/index.umd.cjs.map +1 -1
- package/package.json +4 -4
- package/src/__package__.ts +3 -3
- package/src/array.ts +97 -97
- package/src/cache.ts +65 -65
- package/src/debounce.ts +88 -88
- package/src/dictionary.ts +69 -69
- package/src/dispatch.ts +125 -125
- package/src/esp.ts +32 -32
- package/src/graph.ts +353 -353
- package/src/graph2.ts +675 -675
- package/src/hashSum.ts +55 -55
- package/src/immutable.ts +156 -156
- package/src/index.ts +21 -21
- package/src/logging.ts +212 -212
- package/src/math.ts +92 -92
- package/src/object.ts +122 -122
- package/src/observer.ts +91 -91
- package/src/platform.ts +20 -20
- package/src/saxParser.ts +135 -135
- package/src/stack.ts +41 -41
- package/src/stateful.ts +178 -178
- package/src/string.ts +21 -21
- package/src/url.ts +27 -27
- package/src/utf8ToBase64.ts +47 -47
package/src/graph.ts
CHANGED
|
@@ -1,353 +1,353 @@
|
|
|
1
|
-
export class GraphItem<S, V, E> {
|
|
2
|
-
protected _graph: Graph<S, V, E>;
|
|
3
|
-
readonly parent: Subgraph<S, V, E> | null;
|
|
4
|
-
readonly props: { [key: string]: any } = {};
|
|
5
|
-
|
|
6
|
-
constructor(graph: Graph<S, V, E>, parent: Subgraph<S, V, E> | null) {
|
|
7
|
-
this._graph = graph;
|
|
8
|
-
this.parent = parent;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export class Subgraph<S, V, E> extends GraphItem<S, V, E> {
|
|
13
|
-
readonly subgraphs: Array<Subgraph<S, V, E>> = [];
|
|
14
|
-
readonly vertices: Array<Vertex<S, V, E>> = [];
|
|
15
|
-
readonly edges: Array<Edge<S, V, E>> = [];
|
|
16
|
-
readonly _?: S;
|
|
17
|
-
|
|
18
|
-
constructor(graph: Graph<S, V, E>, parent: Subgraph<S, V, E> | null, _?: S) {
|
|
19
|
-
super(graph, parent);
|
|
20
|
-
if (parent) { // Only needed for dummy root
|
|
21
|
-
parent._addSubgraph(this);
|
|
22
|
-
}
|
|
23
|
-
this._ = _;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
remove(full: boolean = true): void {
|
|
27
|
-
this._graph.removeSubgraph(this, full);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
createSubgraph(_?: S): Subgraph<S, V, E> {
|
|
31
|
-
return this._graph.createSubgraph(this, _);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
_addSubgraph(subgraph: Subgraph<S, V, E>) {
|
|
35
|
-
if (this.subgraphs.indexOf(subgraph) >= 0) {
|
|
36
|
-
throw new Error("Subgraph already exists");
|
|
37
|
-
}
|
|
38
|
-
this.subgraphs.push(subgraph);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
_removeSubgraph(subgraph: Subgraph<S, V, E>) {
|
|
42
|
-
const idx = this.subgraphs.indexOf(subgraph);
|
|
43
|
-
if (idx < 0) {
|
|
44
|
-
throw new Error("Subgraph does not exist");
|
|
45
|
-
}
|
|
46
|
-
this.subgraphs.splice(idx, 1);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
removeAllSubgraphs() {
|
|
50
|
-
for (let i = this.subgraphs.length - 1; i >= 0; --i) {
|
|
51
|
-
this._graph.removeSubgraph(this.subgraphs[i], true);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
createVertex(_?: V): Vertex<S, V, E> {
|
|
56
|
-
return this._graph.createVertex(this, _);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
_addVertex(vertex: Vertex<S, V, E>) {
|
|
60
|
-
if (this.vertices.indexOf(vertex) >= 0) {
|
|
61
|
-
throw new Error("Vertex already exists");
|
|
62
|
-
}
|
|
63
|
-
this.vertices.push(vertex);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
_removeVertex(vertex: Vertex<S, V, E>) {
|
|
67
|
-
const idx = this.vertices.indexOf(vertex);
|
|
68
|
-
if (idx < 0) {
|
|
69
|
-
throw new Error("Vertex does not exist");
|
|
70
|
-
}
|
|
71
|
-
this.vertices.splice(idx, 1);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
removeAllVertices() {
|
|
75
|
-
for (let i = this.vertices.length - 1; i >= 0; --i) {
|
|
76
|
-
this._graph.removeVertex(this.vertices[i], true);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
createEdge(source: Vertex<S, V, E>, target: Vertex<S, V, E>, _?: E): Edge<S, V, E> {
|
|
81
|
-
return this._graph.createEdge(this, source, target, _);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
_addEdge(edge: Edge<S, V, E>) {
|
|
85
|
-
if (this.edges.indexOf(edge) >= 0) {
|
|
86
|
-
throw new Error("Edge already exists");
|
|
87
|
-
}
|
|
88
|
-
this.edges.push(edge);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
_removeEdge(edge: Edge<S, V, E>) {
|
|
92
|
-
const idx = this.edges.indexOf(edge);
|
|
93
|
-
if (idx < 0) {
|
|
94
|
-
throw new Error("Edge does not exist");
|
|
95
|
-
}
|
|
96
|
-
this.edges.splice(idx, 1);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
_add(item: Subgraph<S, V, E> | Vertex<S, V, E> | Edge<S, V, E>) {
|
|
100
|
-
if (item instanceof Subgraph) {
|
|
101
|
-
this._addSubgraph(item);
|
|
102
|
-
} else if (item instanceof Vertex) {
|
|
103
|
-
this._addVertex(item);
|
|
104
|
-
} else {
|
|
105
|
-
this._addEdge(item);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export class Vertex<S, V, E> extends GraphItem<S, V, E> {
|
|
111
|
-
readonly inEdges: Array<Edge<S, V, E>> = [];
|
|
112
|
-
readonly outEdges: Array<Edge<S, V, E>> = [];
|
|
113
|
-
get edges(): ReadonlyArray<Edge<S, V, E>> {
|
|
114
|
-
return [...this.inEdges, ...this.outEdges];
|
|
115
|
-
}
|
|
116
|
-
readonly _?: V;
|
|
117
|
-
|
|
118
|
-
constructor(graph: Graph<S, V, E>, parent: Subgraph<S, V, E>, _?: V) {
|
|
119
|
-
super(graph, parent);
|
|
120
|
-
parent._addVertex(this);
|
|
121
|
-
this._ = _;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
remove(full: boolean = true, _?: (source: V, target: V) => E) {
|
|
125
|
-
return this._graph.removeVertex(this, full, _);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
addInEdge(edge: Edge<S, V, E>) {
|
|
129
|
-
this.inEdges.push(edge);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
removeInEdge(edge: Edge<S, V, E>) {
|
|
133
|
-
const idx = this.inEdges.indexOf(edge);
|
|
134
|
-
if (idx < 0) {
|
|
135
|
-
throw new Error("In edge does not exist");
|
|
136
|
-
}
|
|
137
|
-
this.inEdges.splice(idx, 1);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
addOutEdge(edge: Edge<S, V, E>) {
|
|
141
|
-
this.outEdges.push(edge);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
removeOutEdge(edge: Edge<S, V, E>) {
|
|
145
|
-
const idx = this.outEdges.indexOf(edge);
|
|
146
|
-
if (idx < 0) {
|
|
147
|
-
throw new Error("Out edge does not exist");
|
|
148
|
-
}
|
|
149
|
-
this.outEdges.splice(idx, 1);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
export class Edge<S, V, E> extends GraphItem<S, V, E> {
|
|
154
|
-
readonly source: Vertex<S, V, E>;
|
|
155
|
-
readonly target: Vertex<S, V, E>;
|
|
156
|
-
readonly _?: E;
|
|
157
|
-
|
|
158
|
-
constructor(graph: Graph<S, V, E>, parent: Subgraph<S, V, E>, source: Vertex<S, V, E>, target: Vertex<S, V, E>, _?: E) {
|
|
159
|
-
super(graph, parent);
|
|
160
|
-
if (!source) {
|
|
161
|
-
throw new Error("Missing source vertex");
|
|
162
|
-
}
|
|
163
|
-
if (!target) {
|
|
164
|
-
throw new Error("Missing target vertex");
|
|
165
|
-
}
|
|
166
|
-
parent._addEdge(this);
|
|
167
|
-
this.source = source;
|
|
168
|
-
this.source.addOutEdge(this);
|
|
169
|
-
this.target = target;
|
|
170
|
-
this.target.addInEdge(this);
|
|
171
|
-
this._ = _;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
remove(): void {
|
|
175
|
-
this._graph.removeEdge(this);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export class Graph<S = undefined, V = undefined, E = undefined> {
|
|
180
|
-
readonly root: Subgraph<S, V, E>;
|
|
181
|
-
private _allSubgraphs: Array<Subgraph<S, V, E>> = [];
|
|
182
|
-
private _allSubgraphsMap: { [id: string]: Subgraph<S, V, E> } = {};
|
|
183
|
-
private _allVertices: Array<Vertex<S, V, E>> = [];
|
|
184
|
-
private _allVerticesMap: { [id: string]: Vertex<S, V, E> } = {};
|
|
185
|
-
private _allEdges: Array<Edge<S, V, E>> = [];
|
|
186
|
-
private _allEdgesMap: { [id: string]: Edge<S, V, E> } = {};
|
|
187
|
-
|
|
188
|
-
idOf: (item: Subgraph<S, V, E> | Vertex<S, V, E> | Edge<S, V, E>) => string;
|
|
189
|
-
|
|
190
|
-
constructor(idOf: (item: Subgraph<S, V, E> | Vertex<S, V, E> | Edge<S, V, E>) => string = item => "" + item._, _?: S) {
|
|
191
|
-
this.root = new Subgraph(this, null, _);
|
|
192
|
-
this.idOf = idOf;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
createSubgraph(parent?: Subgraph<S, V, E>, _?: S): Subgraph<S, V, E> {
|
|
196
|
-
const retVal = new Subgraph(this, parent || this.root, _);
|
|
197
|
-
this._allSubgraphs.push(retVal);
|
|
198
|
-
this._allSubgraphsMap[this.idOf(retVal)] = retVal;
|
|
199
|
-
return retVal;
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
removeSubgraph(subgraph: Subgraph<S, V, E>, full: boolean = true) {
|
|
203
|
-
const idx = this._allSubgraphs.indexOf(subgraph);
|
|
204
|
-
if (idx < 0) {
|
|
205
|
-
throw new Error("Subgraph does not exist");
|
|
206
|
-
}
|
|
207
|
-
this._allSubgraphs.splice(idx, 1);
|
|
208
|
-
delete this._allSubgraphsMap[this.idOf(subgraph)];
|
|
209
|
-
if (subgraph.parent) {
|
|
210
|
-
subgraph.parent._removeSubgraph(subgraph);
|
|
211
|
-
}
|
|
212
|
-
subgraph.edges.forEach(edge => full ? this.removeEdge(edge) : subgraph.parent!._addEdge(edge));
|
|
213
|
-
subgraph.vertices.forEach(vertex => full ? this.removeVertex(vertex, full) : subgraph.parent!._addVertex(vertex));
|
|
214
|
-
subgraph.subgraphs.forEach(childSubgraph => full ? this.removeSubgraph(childSubgraph, full) : subgraph.parent!._addSubgraph(childSubgraph)
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
get subgraphs(): ReadonlyArray<Subgraph<S, V, E>> {
|
|
219
|
-
return this._allSubgraphs;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
subgraph(id: string): Subgraph<S, V, E> {
|
|
223
|
-
return this._allSubgraphsMap[id];
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
createVertex(parent: Subgraph<S, V, E>, _?: V): Vertex<S, V, E> {
|
|
227
|
-
const retVal = new Vertex(this, parent, _);
|
|
228
|
-
this._allVertices.push(retVal);
|
|
229
|
-
this._allVerticesMap[this.idOf(retVal)] = retVal;
|
|
230
|
-
return retVal;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
removeVertex(vertex: Vertex<S, V, E>, full: boolean = true, _?: (source: V, target: V) => E) {
|
|
234
|
-
const idx = this._allVertices.indexOf(vertex);
|
|
235
|
-
if (idx < 0) {
|
|
236
|
-
throw new Error("Vertex does not exist");
|
|
237
|
-
}
|
|
238
|
-
this._allVertices.splice(idx, 1);
|
|
239
|
-
delete this._allVerticesMap[this.idOf(vertex)];
|
|
240
|
-
if (vertex.parent) {
|
|
241
|
-
vertex.parent._removeVertex(vertex);
|
|
242
|
-
}
|
|
243
|
-
if (!full) {
|
|
244
|
-
vertex.inEdges.forEach(inEdge => {
|
|
245
|
-
vertex.outEdges.forEach(outEdge => {
|
|
246
|
-
this.createEdge(this.root, inEdge.source, outEdge.target, _ ? _(inEdge.source._!, outEdge.target._!) : undefined);
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
vertex.inEdges.forEach(edge => this.removeEdge(edge));
|
|
251
|
-
vertex.outEdges.forEach(edge => this.removeEdge(edge));
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
get vertices(): ReadonlyArray<Vertex<S, V, E>> {
|
|
255
|
-
return this._allVertices;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
vertex(id: string): Vertex<S, V, E> {
|
|
259
|
-
return this._allVerticesMap[id];
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
createEdge(parent: Subgraph<S, V, E>, source: Vertex<S, V, E>, target: Vertex<S, V, E>, _?: E): Edge<S, V, E> {
|
|
263
|
-
const retVal = new Edge<S, V, E>(this, parent, source, target, _);
|
|
264
|
-
this._allEdges.push(retVal);
|
|
265
|
-
this._allEdgesMap[this.idOf(retVal)] = retVal;
|
|
266
|
-
return retVal;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
removeEdge(edge: Edge<S, V, E>) {
|
|
270
|
-
const idx = this._allEdges.indexOf(edge);
|
|
271
|
-
if (idx < 0) {
|
|
272
|
-
throw new Error("Edge does not exist");
|
|
273
|
-
}
|
|
274
|
-
this._allEdges.splice(idx, 1);
|
|
275
|
-
delete this._allEdgesMap[this.idOf(edge)];
|
|
276
|
-
if (edge.parent) {
|
|
277
|
-
edge.parent._removeEdge(edge);
|
|
278
|
-
}
|
|
279
|
-
edge.source.removeOutEdge(edge);
|
|
280
|
-
edge.target.removeInEdge(edge);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
get edges(): ReadonlyArray<Edge<S, V, E>> {
|
|
284
|
-
return this._allEdges;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
edge(id: string): Edge<S, V, E> {
|
|
288
|
-
return this._allEdgesMap[id];
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
private _walk(parent: Subgraph<S, V, E>, visitor: (item: GraphItem<S, V, E>) => "abort" | "stepover" | void): true | false | void {
|
|
292
|
-
for (const subgraph of parent.subgraphs) {
|
|
293
|
-
switch (visitor(subgraph)) {
|
|
294
|
-
case "abort":
|
|
295
|
-
return true;
|
|
296
|
-
case "stepover":
|
|
297
|
-
break;
|
|
298
|
-
default:
|
|
299
|
-
if (this._walk(subgraph, visitor)) return true;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
for (const vertex of parent.vertices) {
|
|
303
|
-
if (visitor(vertex) === "abort") return true;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
walk(visitor: (visitor: GraphItem<S, V, E>) => "abort" | "stepover" | void) {
|
|
308
|
-
this._walk(this.root, visitor);
|
|
309
|
-
for (const edge of this._allEdges) {
|
|
310
|
-
if (visitor(edge) === "abort") return true;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
clone(): Graph<S, V, E> {
|
|
315
|
-
const ctor: new (idOf: (item: Subgraph<S, V, E> | Vertex<S, V, E> | Edge<S, V, E>) => string, _?: S) => Graph<S, V, E> = this.constructor as any;
|
|
316
|
-
const retVal = new ctor(this.idOf, this.root._);
|
|
317
|
-
const map = ObjMap();
|
|
318
|
-
map.put(this.root, retVal.root);
|
|
319
|
-
this.walk(item => {
|
|
320
|
-
const parent = map.get(item.parent);
|
|
321
|
-
if (item instanceof Subgraph) {
|
|
322
|
-
map.put(item, parent.createSubgraph(item._));
|
|
323
|
-
} else if (item instanceof Vertex) {
|
|
324
|
-
map.put(item, parent.createVertex(item._));
|
|
325
|
-
} else if (item instanceof Edge) {
|
|
326
|
-
const source = map.get(item.source);
|
|
327
|
-
const target = map.get(item.target);
|
|
328
|
-
parent.createEdge(source, target, item._);
|
|
329
|
-
}
|
|
330
|
-
});
|
|
331
|
-
return retVal;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
function ObjMap() {
|
|
336
|
-
const keys: any[] = [];
|
|
337
|
-
const values: any[] = [];
|
|
338
|
-
|
|
339
|
-
return {
|
|
340
|
-
put(key: any, value: any) {
|
|
341
|
-
const index = keys.indexOf(key);
|
|
342
|
-
if (index === -1) {
|
|
343
|
-
keys.push(key);
|
|
344
|
-
values.push(value);
|
|
345
|
-
} else {
|
|
346
|
-
values[index] = value;
|
|
347
|
-
}
|
|
348
|
-
},
|
|
349
|
-
get(key: any) {
|
|
350
|
-
return values[keys.indexOf(key)];
|
|
351
|
-
}
|
|
352
|
-
};
|
|
353
|
-
}
|
|
1
|
+
export class GraphItem<S, V, E> {
|
|
2
|
+
protected _graph: Graph<S, V, E>;
|
|
3
|
+
readonly parent: Subgraph<S, V, E> | null;
|
|
4
|
+
readonly props: { [key: string]: any } = {};
|
|
5
|
+
|
|
6
|
+
constructor(graph: Graph<S, V, E>, parent: Subgraph<S, V, E> | null) {
|
|
7
|
+
this._graph = graph;
|
|
8
|
+
this.parent = parent;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class Subgraph<S, V, E> extends GraphItem<S, V, E> {
|
|
13
|
+
readonly subgraphs: Array<Subgraph<S, V, E>> = [];
|
|
14
|
+
readonly vertices: Array<Vertex<S, V, E>> = [];
|
|
15
|
+
readonly edges: Array<Edge<S, V, E>> = [];
|
|
16
|
+
readonly _?: S;
|
|
17
|
+
|
|
18
|
+
constructor(graph: Graph<S, V, E>, parent: Subgraph<S, V, E> | null, _?: S) {
|
|
19
|
+
super(graph, parent);
|
|
20
|
+
if (parent) { // Only needed for dummy root
|
|
21
|
+
parent._addSubgraph(this);
|
|
22
|
+
}
|
|
23
|
+
this._ = _;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
remove(full: boolean = true): void {
|
|
27
|
+
this._graph.removeSubgraph(this, full);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
createSubgraph(_?: S): Subgraph<S, V, E> {
|
|
31
|
+
return this._graph.createSubgraph(this, _);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
_addSubgraph(subgraph: Subgraph<S, V, E>) {
|
|
35
|
+
if (this.subgraphs.indexOf(subgraph) >= 0) {
|
|
36
|
+
throw new Error("Subgraph already exists");
|
|
37
|
+
}
|
|
38
|
+
this.subgraphs.push(subgraph);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
_removeSubgraph(subgraph: Subgraph<S, V, E>) {
|
|
42
|
+
const idx = this.subgraphs.indexOf(subgraph);
|
|
43
|
+
if (idx < 0) {
|
|
44
|
+
throw new Error("Subgraph does not exist");
|
|
45
|
+
}
|
|
46
|
+
this.subgraphs.splice(idx, 1);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
removeAllSubgraphs() {
|
|
50
|
+
for (let i = this.subgraphs.length - 1; i >= 0; --i) {
|
|
51
|
+
this._graph.removeSubgraph(this.subgraphs[i], true);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
createVertex(_?: V): Vertex<S, V, E> {
|
|
56
|
+
return this._graph.createVertex(this, _);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
_addVertex(vertex: Vertex<S, V, E>) {
|
|
60
|
+
if (this.vertices.indexOf(vertex) >= 0) {
|
|
61
|
+
throw new Error("Vertex already exists");
|
|
62
|
+
}
|
|
63
|
+
this.vertices.push(vertex);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
_removeVertex(vertex: Vertex<S, V, E>) {
|
|
67
|
+
const idx = this.vertices.indexOf(vertex);
|
|
68
|
+
if (idx < 0) {
|
|
69
|
+
throw new Error("Vertex does not exist");
|
|
70
|
+
}
|
|
71
|
+
this.vertices.splice(idx, 1);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
removeAllVertices() {
|
|
75
|
+
for (let i = this.vertices.length - 1; i >= 0; --i) {
|
|
76
|
+
this._graph.removeVertex(this.vertices[i], true);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
createEdge(source: Vertex<S, V, E>, target: Vertex<S, V, E>, _?: E): Edge<S, V, E> {
|
|
81
|
+
return this._graph.createEdge(this, source, target, _);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_addEdge(edge: Edge<S, V, E>) {
|
|
85
|
+
if (this.edges.indexOf(edge) >= 0) {
|
|
86
|
+
throw new Error("Edge already exists");
|
|
87
|
+
}
|
|
88
|
+
this.edges.push(edge);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
_removeEdge(edge: Edge<S, V, E>) {
|
|
92
|
+
const idx = this.edges.indexOf(edge);
|
|
93
|
+
if (idx < 0) {
|
|
94
|
+
throw new Error("Edge does not exist");
|
|
95
|
+
}
|
|
96
|
+
this.edges.splice(idx, 1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_add(item: Subgraph<S, V, E> | Vertex<S, V, E> | Edge<S, V, E>) {
|
|
100
|
+
if (item instanceof Subgraph) {
|
|
101
|
+
this._addSubgraph(item);
|
|
102
|
+
} else if (item instanceof Vertex) {
|
|
103
|
+
this._addVertex(item);
|
|
104
|
+
} else {
|
|
105
|
+
this._addEdge(item);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export class Vertex<S, V, E> extends GraphItem<S, V, E> {
|
|
111
|
+
readonly inEdges: Array<Edge<S, V, E>> = [];
|
|
112
|
+
readonly outEdges: Array<Edge<S, V, E>> = [];
|
|
113
|
+
get edges(): ReadonlyArray<Edge<S, V, E>> {
|
|
114
|
+
return [...this.inEdges, ...this.outEdges];
|
|
115
|
+
}
|
|
116
|
+
readonly _?: V;
|
|
117
|
+
|
|
118
|
+
constructor(graph: Graph<S, V, E>, parent: Subgraph<S, V, E>, _?: V) {
|
|
119
|
+
super(graph, parent);
|
|
120
|
+
parent._addVertex(this);
|
|
121
|
+
this._ = _;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
remove(full: boolean = true, _?: (source: V, target: V) => E) {
|
|
125
|
+
return this._graph.removeVertex(this, full, _);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
addInEdge(edge: Edge<S, V, E>) {
|
|
129
|
+
this.inEdges.push(edge);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
removeInEdge(edge: Edge<S, V, E>) {
|
|
133
|
+
const idx = this.inEdges.indexOf(edge);
|
|
134
|
+
if (idx < 0) {
|
|
135
|
+
throw new Error("In edge does not exist");
|
|
136
|
+
}
|
|
137
|
+
this.inEdges.splice(idx, 1);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
addOutEdge(edge: Edge<S, V, E>) {
|
|
141
|
+
this.outEdges.push(edge);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
removeOutEdge(edge: Edge<S, V, E>) {
|
|
145
|
+
const idx = this.outEdges.indexOf(edge);
|
|
146
|
+
if (idx < 0) {
|
|
147
|
+
throw new Error("Out edge does not exist");
|
|
148
|
+
}
|
|
149
|
+
this.outEdges.splice(idx, 1);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export class Edge<S, V, E> extends GraphItem<S, V, E> {
|
|
154
|
+
readonly source: Vertex<S, V, E>;
|
|
155
|
+
readonly target: Vertex<S, V, E>;
|
|
156
|
+
readonly _?: E;
|
|
157
|
+
|
|
158
|
+
constructor(graph: Graph<S, V, E>, parent: Subgraph<S, V, E>, source: Vertex<S, V, E>, target: Vertex<S, V, E>, _?: E) {
|
|
159
|
+
super(graph, parent);
|
|
160
|
+
if (!source) {
|
|
161
|
+
throw new Error("Missing source vertex");
|
|
162
|
+
}
|
|
163
|
+
if (!target) {
|
|
164
|
+
throw new Error("Missing target vertex");
|
|
165
|
+
}
|
|
166
|
+
parent._addEdge(this);
|
|
167
|
+
this.source = source;
|
|
168
|
+
this.source.addOutEdge(this);
|
|
169
|
+
this.target = target;
|
|
170
|
+
this.target.addInEdge(this);
|
|
171
|
+
this._ = _;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
remove(): void {
|
|
175
|
+
this._graph.removeEdge(this);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export class Graph<S = undefined, V = undefined, E = undefined> {
|
|
180
|
+
readonly root: Subgraph<S, V, E>;
|
|
181
|
+
private _allSubgraphs: Array<Subgraph<S, V, E>> = [];
|
|
182
|
+
private _allSubgraphsMap: { [id: string]: Subgraph<S, V, E> } = {};
|
|
183
|
+
private _allVertices: Array<Vertex<S, V, E>> = [];
|
|
184
|
+
private _allVerticesMap: { [id: string]: Vertex<S, V, E> } = {};
|
|
185
|
+
private _allEdges: Array<Edge<S, V, E>> = [];
|
|
186
|
+
private _allEdgesMap: { [id: string]: Edge<S, V, E> } = {};
|
|
187
|
+
|
|
188
|
+
idOf: (item: Subgraph<S, V, E> | Vertex<S, V, E> | Edge<S, V, E>) => string;
|
|
189
|
+
|
|
190
|
+
constructor(idOf: (item: Subgraph<S, V, E> | Vertex<S, V, E> | Edge<S, V, E>) => string = item => "" + item._, _?: S) {
|
|
191
|
+
this.root = new Subgraph(this, null, _);
|
|
192
|
+
this.idOf = idOf;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
createSubgraph(parent?: Subgraph<S, V, E>, _?: S): Subgraph<S, V, E> {
|
|
196
|
+
const retVal = new Subgraph(this, parent || this.root, _);
|
|
197
|
+
this._allSubgraphs.push(retVal);
|
|
198
|
+
this._allSubgraphsMap[this.idOf(retVal)] = retVal;
|
|
199
|
+
return retVal;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
removeSubgraph(subgraph: Subgraph<S, V, E>, full: boolean = true) {
|
|
203
|
+
const idx = this._allSubgraphs.indexOf(subgraph);
|
|
204
|
+
if (idx < 0) {
|
|
205
|
+
throw new Error("Subgraph does not exist");
|
|
206
|
+
}
|
|
207
|
+
this._allSubgraphs.splice(idx, 1);
|
|
208
|
+
delete this._allSubgraphsMap[this.idOf(subgraph)];
|
|
209
|
+
if (subgraph.parent) {
|
|
210
|
+
subgraph.parent._removeSubgraph(subgraph);
|
|
211
|
+
}
|
|
212
|
+
subgraph.edges.forEach(edge => full ? this.removeEdge(edge) : subgraph.parent!._addEdge(edge));
|
|
213
|
+
subgraph.vertices.forEach(vertex => full ? this.removeVertex(vertex, full) : subgraph.parent!._addVertex(vertex));
|
|
214
|
+
subgraph.subgraphs.forEach(childSubgraph => full ? this.removeSubgraph(childSubgraph, full) : subgraph.parent!._addSubgraph(childSubgraph)
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
get subgraphs(): ReadonlyArray<Subgraph<S, V, E>> {
|
|
219
|
+
return this._allSubgraphs;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
subgraph(id: string): Subgraph<S, V, E> {
|
|
223
|
+
return this._allSubgraphsMap[id];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
createVertex(parent: Subgraph<S, V, E>, _?: V): Vertex<S, V, E> {
|
|
227
|
+
const retVal = new Vertex(this, parent, _);
|
|
228
|
+
this._allVertices.push(retVal);
|
|
229
|
+
this._allVerticesMap[this.idOf(retVal)] = retVal;
|
|
230
|
+
return retVal;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
removeVertex(vertex: Vertex<S, V, E>, full: boolean = true, _?: (source: V, target: V) => E) {
|
|
234
|
+
const idx = this._allVertices.indexOf(vertex);
|
|
235
|
+
if (idx < 0) {
|
|
236
|
+
throw new Error("Vertex does not exist");
|
|
237
|
+
}
|
|
238
|
+
this._allVertices.splice(idx, 1);
|
|
239
|
+
delete this._allVerticesMap[this.idOf(vertex)];
|
|
240
|
+
if (vertex.parent) {
|
|
241
|
+
vertex.parent._removeVertex(vertex);
|
|
242
|
+
}
|
|
243
|
+
if (!full) {
|
|
244
|
+
vertex.inEdges.forEach(inEdge => {
|
|
245
|
+
vertex.outEdges.forEach(outEdge => {
|
|
246
|
+
this.createEdge(this.root, inEdge.source, outEdge.target, _ ? _(inEdge.source._!, outEdge.target._!) : undefined);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
vertex.inEdges.forEach(edge => this.removeEdge(edge));
|
|
251
|
+
vertex.outEdges.forEach(edge => this.removeEdge(edge));
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
get vertices(): ReadonlyArray<Vertex<S, V, E>> {
|
|
255
|
+
return this._allVertices;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
vertex(id: string): Vertex<S, V, E> {
|
|
259
|
+
return this._allVerticesMap[id];
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
createEdge(parent: Subgraph<S, V, E>, source: Vertex<S, V, E>, target: Vertex<S, V, E>, _?: E): Edge<S, V, E> {
|
|
263
|
+
const retVal = new Edge<S, V, E>(this, parent, source, target, _);
|
|
264
|
+
this._allEdges.push(retVal);
|
|
265
|
+
this._allEdgesMap[this.idOf(retVal)] = retVal;
|
|
266
|
+
return retVal;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
removeEdge(edge: Edge<S, V, E>) {
|
|
270
|
+
const idx = this._allEdges.indexOf(edge);
|
|
271
|
+
if (idx < 0) {
|
|
272
|
+
throw new Error("Edge does not exist");
|
|
273
|
+
}
|
|
274
|
+
this._allEdges.splice(idx, 1);
|
|
275
|
+
delete this._allEdgesMap[this.idOf(edge)];
|
|
276
|
+
if (edge.parent) {
|
|
277
|
+
edge.parent._removeEdge(edge);
|
|
278
|
+
}
|
|
279
|
+
edge.source.removeOutEdge(edge);
|
|
280
|
+
edge.target.removeInEdge(edge);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
get edges(): ReadonlyArray<Edge<S, V, E>> {
|
|
284
|
+
return this._allEdges;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
edge(id: string): Edge<S, V, E> {
|
|
288
|
+
return this._allEdgesMap[id];
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private _walk(parent: Subgraph<S, V, E>, visitor: (item: GraphItem<S, V, E>) => "abort" | "stepover" | void): true | false | void {
|
|
292
|
+
for (const subgraph of parent.subgraphs) {
|
|
293
|
+
switch (visitor(subgraph)) {
|
|
294
|
+
case "abort":
|
|
295
|
+
return true;
|
|
296
|
+
case "stepover":
|
|
297
|
+
break;
|
|
298
|
+
default:
|
|
299
|
+
if (this._walk(subgraph, visitor)) return true;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
for (const vertex of parent.vertices) {
|
|
303
|
+
if (visitor(vertex) === "abort") return true;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
walk(visitor: (visitor: GraphItem<S, V, E>) => "abort" | "stepover" | void) {
|
|
308
|
+
this._walk(this.root, visitor);
|
|
309
|
+
for (const edge of this._allEdges) {
|
|
310
|
+
if (visitor(edge) === "abort") return true;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
clone(): Graph<S, V, E> {
|
|
315
|
+
const ctor: new (idOf: (item: Subgraph<S, V, E> | Vertex<S, V, E> | Edge<S, V, E>) => string, _?: S) => Graph<S, V, E> = this.constructor as any;
|
|
316
|
+
const retVal = new ctor(this.idOf, this.root._);
|
|
317
|
+
const map = ObjMap();
|
|
318
|
+
map.put(this.root, retVal.root);
|
|
319
|
+
this.walk(item => {
|
|
320
|
+
const parent = map.get(item.parent);
|
|
321
|
+
if (item instanceof Subgraph) {
|
|
322
|
+
map.put(item, parent.createSubgraph(item._));
|
|
323
|
+
} else if (item instanceof Vertex) {
|
|
324
|
+
map.put(item, parent.createVertex(item._));
|
|
325
|
+
} else if (item instanceof Edge) {
|
|
326
|
+
const source = map.get(item.source);
|
|
327
|
+
const target = map.get(item.target);
|
|
328
|
+
parent.createEdge(source, target, item._);
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
return retVal;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function ObjMap() {
|
|
336
|
+
const keys: any[] = [];
|
|
337
|
+
const values: any[] = [];
|
|
338
|
+
|
|
339
|
+
return {
|
|
340
|
+
put(key: any, value: any) {
|
|
341
|
+
const index = keys.indexOf(key);
|
|
342
|
+
if (index === -1) {
|
|
343
|
+
keys.push(key);
|
|
344
|
+
values.push(value);
|
|
345
|
+
} else {
|
|
346
|
+
values[index] = value;
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
get(key: any) {
|
|
350
|
+
return values[keys.indexOf(key)];
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
}
|