/
NodeCollectionDeserializer.ts
151 lines (133 loc) · 5.59 KB
/
NodeCollectionDeserializer.ts
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*!
* Copyright 2021 Cognite AS
*/
import assert from 'assert';
import { CogniteClient } from '@cognite/sdk';
import { NumericRange, IndexSet } from '@reveal/utilities';
import { Cognite3DModel } from '../../../migration';
import { AssetNodeCollection } from './AssetNodeCollection';
import { PropertyFilterNodeCollection } from './PropertyFilterNodeCollection';
import { InvertedNodeCollection } from './InvertedNodeCollection';
import { SinglePropertyFilterNodeCollection } from './SinglePropertyFilterNodeCollection';
import {
NodeCollectionBase,
TreeIndexNodeCollection,
IntersectionNodeCollection,
UnionNodeCollection
} from '@reveal/cad-styling';
export type TypeName = string;
export type NodeCollectionSerializationContext = { client: CogniteClient; model: Cognite3DModel };
export type NodeCollectionDescriptor = { token: TypeName; state: any; options?: any };
export class NodeCollectionDeserializer {
public static readonly Instance = new NodeCollectionDeserializer();
private readonly _types = new Map<
TypeName,
{
deserializer: (
state: NodeCollectionDescriptor,
context: NodeCollectionSerializationContext
) => Promise<NodeCollectionBase>;
}
>();
private constructor() {
this._types = new Map();
this.registerWellKnownNodeCollectionTypes();
}
registerNodeCollectionType<T extends NodeCollectionBase>(
nodeCollectionType: TypeName,
deserializer: (descriptor: NodeCollectionDescriptor, context: NodeCollectionSerializationContext) => Promise<T>
): void {
this._types.set(nodeCollectionType, {
deserializer: (descriptor: NodeCollectionDescriptor, context: NodeCollectionSerializationContext) =>
deserializer(descriptor, context) as Promise<T>
});
}
async deserialize(
// TODO 2021-10-01 larsmoa: Avoid forcing node collections to rely on CogniteClient
// to support more generic deployment scenarios.
client: CogniteClient,
model: Cognite3DModel,
descriptor: NodeCollectionDescriptor
): Promise<NodeCollectionBase> {
const context: NodeCollectionSerializationContext = { client, model };
const deserializer = this.getDeserializer(descriptor.token);
return deserializer(descriptor, context);
}
private getDeserializer(typeName: TypeName) {
const entry = this._types.get(typeName);
assert(entry !== undefined);
return entry!.deserializer;
}
private registerWellKnownNodeCollectionTypes() {
this.registerNodeCollectionType<AssetNodeCollection>(
AssetNodeCollection.classToken,
async (descriptor, context) => {
const nodeCollection = new AssetNodeCollection(context.client, context.model);
await nodeCollection.executeFilter(descriptor.state);
return nodeCollection;
}
);
this.registerNodeCollectionType<PropertyFilterNodeCollection>(
PropertyFilterNodeCollection.classToken,
async (descriptor, context) => {
const nodeCollection = new PropertyFilterNodeCollection(context.client, context.model, descriptor.options);
await nodeCollection.executeFilter(descriptor.state);
return nodeCollection;
}
);
this.registerNodeCollectionType<SinglePropertyFilterNodeCollection>(
SinglePropertyFilterNodeCollection.classToken,
async (descriptor, context) => {
const nodeCollection = new SinglePropertyFilterNodeCollection(
context.client,
context.model,
descriptor.options
);
const { propertyCategory, propertyKey, propertyValues } = descriptor.state;
await nodeCollection.executeFilter(propertyCategory, propertyKey, propertyValues);
return nodeCollection;
}
);
this.registerNodeCollectionType<TreeIndexNodeCollection>(TreeIndexNodeCollection.classToken, descriptor => {
const indexSet = new IndexSet();
descriptor.state.forEach((range: NumericRange) => indexSet.addRange(new NumericRange(range.from, range.count)));
const nodeCollection = new TreeIndexNodeCollection(indexSet);
return Promise.resolve(nodeCollection);
});
this.registerNodeCollectionType<IntersectionNodeCollection>(
IntersectionNodeCollection.classToken,
async (descriptor, context) => {
const subCollections: NodeCollectionBase[] = await Promise.all(
descriptor.state.subCollections.map((subSet: any) => {
return this.deserialize(context.client, context.model, subSet);
})
);
return new IntersectionNodeCollection(subCollections);
}
);
this.registerNodeCollectionType<UnionNodeCollection>(
UnionNodeCollection.classToken,
async (descriptor, context) => {
const subCollections: NodeCollectionBase[] = await Promise.all(
descriptor.state.subCollections.map((subSet: any) => {
return this.deserialize(context.client, context.model, subSet);
})
);
return new UnionNodeCollection(subCollections);
}
);
this.registerNodeCollectionType<InvertedNodeCollection>(
InvertedNodeCollection.classToken,
async (descriptor, context) => {
const innerCollection = await this.deserialize(context.client, context.model, descriptor.state.innerSet);
return new InvertedNodeCollection(context.model, innerCollection);
}
);
}
}
export function registerCustomNodeCollectionType<T extends NodeCollectionBase>(
nodeCollectionType: TypeName,
deserializer: (descriptor: NodeCollectionDescriptor, context: NodeCollectionSerializationContext) => Promise<T>
): void {
NodeCollectionDeserializer.Instance.registerNodeCollectionType(nodeCollectionType, deserializer);
}