/
ContentGraph.js
106 lines (93 loc) 路 3.16 KB
/
ContentGraph.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// @flow strict-local
import type {ContentKey, NodeId} from './types';
import Graph, {type SerializedGraph, type GraphOpts} from './Graph';
import nullthrows from 'nullthrows';
export type ContentGraphOpts<TNode, TEdgeType: number = 1> = {|
...GraphOpts<TNode, TEdgeType>,
_contentKeyToNodeId?: Map<ContentKey, NodeId>,
_nodeIdToContentKey?: Map<NodeId, ContentKey>,
|};
export type SerializedContentGraph<TNode, TEdgeType: number = 1> = {|
...SerializedGraph<TNode, TEdgeType>,
_contentKeyToNodeId: Map<ContentKey, NodeId>,
_nodeIdToContentKey: Map<NodeId, ContentKey>,
|};
export default class ContentGraph<TNode, TEdgeType: number = 1> extends Graph<
TNode,
TEdgeType,
> {
_contentKeyToNodeId: Map<ContentKey, NodeId>;
_nodeIdToContentKey: Map<NodeId, ContentKey>;
constructor(opts: ?ContentGraphOpts<TNode, TEdgeType>) {
if (opts) {
let {
_contentKeyToNodeId = new Map(),
_nodeIdToContentKey = new Map(),
...rest
} = opts;
super(rest);
this._contentKeyToNodeId = _contentKeyToNodeId;
this._nodeIdToContentKey = _nodeIdToContentKey;
} else {
super(opts);
this._contentKeyToNodeId = new Map();
this._nodeIdToContentKey = new Map();
}
}
// $FlowFixMe[prop-missing]
static deserialize(
opts: SerializedContentGraph<TNode, TEdgeType>,
): ContentGraph<TNode, TEdgeType> {
return new ContentGraph({
nodes: opts.nodes,
adjacencyList: opts.adjacencyList,
rootNodeId: opts.rootNodeId,
_contentKeyToNodeId: opts._contentKeyToNodeId,
_nodeIdToContentKey: opts._nodeIdToContentKey,
});
}
// $FlowFixMe[prop-missing]
serialize(): SerializedContentGraph<TNode, TEdgeType> {
return {
...super.serialize(),
_contentKeyToNodeId: this._contentKeyToNodeId,
_nodeIdToContentKey: this._nodeIdToContentKey,
};
}
addNodeByContentKey(contentKey: ContentKey, node: TNode): NodeId {
if (this.hasContentKey(contentKey)) {
throw new Error('Graph already has content key ' + contentKey);
}
let nodeId = super.addNode(node);
this._contentKeyToNodeId.set(contentKey, nodeId);
this._nodeIdToContentKey.set(nodeId, contentKey);
return nodeId;
}
addNodeByContentKeyIfNeeded(contentKey: ContentKey, node: TNode): NodeId {
return this.hasContentKey(contentKey)
? this.getNodeIdByContentKey(contentKey)
: this.addNodeByContentKey(contentKey, node);
}
getNodeByContentKey(contentKey: ContentKey): ?TNode {
let nodeId = this._contentKeyToNodeId.get(contentKey);
if (nodeId != null) {
return super.getNode(nodeId);
}
}
getNodeIdByContentKey(contentKey: ContentKey): NodeId {
return nullthrows(
this._contentKeyToNodeId.get(contentKey),
`Expected content key ${contentKey} to exist`,
);
}
hasContentKey(contentKey: ContentKey): boolean {
return this._contentKeyToNodeId.has(contentKey);
}
removeNode(nodeId: NodeId): void {
this._assertHasNodeId(nodeId);
let contentKey = nullthrows(this._nodeIdToContentKey.get(nodeId));
this._contentKeyToNodeId.delete(contentKey);
this._nodeIdToContentKey.delete(nodeId);
super.removeNode(nodeId);
}
}