@itwin/unified-selection 0.1.0 → 0.2.0
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/CHANGELOG.md +10 -0
- package/README.md +78 -0
- package/lib/cjs/unified-selection/CachingHiliteSetProvider.d.ts +37 -0
- package/lib/cjs/unified-selection/CachingHiliteSetProvider.d.ts.map +1 -0
- package/lib/cjs/unified-selection/CachingHiliteSetProvider.js +65 -0
- package/lib/cjs/unified-selection/CachingHiliteSetProvider.js.map +1 -0
- package/lib/cjs/unified-selection/HiliteSetProvider.d.ts +39 -0
- package/lib/cjs/unified-selection/HiliteSetProvider.d.ts.map +1 -0
- package/lib/cjs/unified-selection/HiliteSetProvider.js +298 -0
- package/lib/cjs/unified-selection/HiliteSetProvider.js.map +1 -0
- package/lib/cjs/unified-selection/SelectionChangeEvent.d.ts +6 -4
- package/lib/cjs/unified-selection/SelectionChangeEvent.d.ts.map +1 -1
- package/lib/cjs/unified-selection/SelectionChangeEvent.js +1 -1
- package/lib/cjs/unified-selection/SelectionChangeEvent.js.map +1 -1
- package/lib/cjs/unified-selection/SelectionScope.d.ts +44 -0
- package/lib/cjs/unified-selection/SelectionScope.d.ts.map +1 -0
- package/lib/cjs/unified-selection/SelectionScope.js +160 -0
- package/lib/cjs/unified-selection/SelectionScope.js.map +1 -0
- package/lib/cjs/unified-selection/SelectionStorage.d.ts +16 -3
- package/lib/cjs/unified-selection/SelectionStorage.d.ts.map +1 -1
- package/lib/cjs/unified-selection/SelectionStorage.js +14 -3
- package/lib/cjs/unified-selection/SelectionStorage.js.map +1 -1
- package/lib/cjs/unified-selection/queries/ECMetadata.d.ts +44 -0
- package/lib/cjs/unified-selection/queries/ECMetadata.d.ts.map +1 -0
- package/lib/cjs/unified-selection/queries/ECMetadata.js +17 -0
- package/lib/cjs/unified-selection/queries/ECMetadata.js.map +1 -0
- package/lib/cjs/unified-selection/queries/ECSqlCore.d.ts +69 -0
- package/lib/cjs/unified-selection/queries/ECSqlCore.d.ts.map +1 -0
- package/lib/cjs/unified-selection/queries/ECSqlCore.js +23 -0
- package/lib/cjs/unified-selection/queries/ECSqlCore.js.map +1 -0
- package/lib/cjs/unified-selection.d.ts +4 -1
- package/lib/cjs/unified-selection.d.ts.map +1 -1
- package/lib/cjs/unified-selection.js +9 -1
- package/lib/cjs/unified-selection.js.map +1 -1
- package/lib/esm/unified-selection/CachingHiliteSetProvider.d.ts +37 -0
- package/lib/esm/unified-selection/CachingHiliteSetProvider.d.ts.map +1 -0
- package/lib/esm/unified-selection/CachingHiliteSetProvider.js +61 -0
- package/lib/esm/unified-selection/CachingHiliteSetProvider.js.map +1 -0
- package/lib/esm/unified-selection/HiliteSetProvider.d.ts +39 -0
- package/lib/esm/unified-selection/HiliteSetProvider.d.ts.map +1 -0
- package/lib/esm/unified-selection/HiliteSetProvider.js +294 -0
- package/lib/esm/unified-selection/HiliteSetProvider.js.map +1 -0
- package/lib/esm/unified-selection/SelectionChangeEvent.d.ts +6 -4
- package/lib/esm/unified-selection/SelectionChangeEvent.d.ts.map +1 -1
- package/lib/esm/unified-selection/SelectionChangeEvent.js +1 -1
- package/lib/esm/unified-selection/SelectionChangeEvent.js.map +1 -1
- package/lib/esm/unified-selection/SelectionScope.d.ts +44 -0
- package/lib/esm/unified-selection/SelectionScope.d.ts.map +1 -0
- package/lib/esm/unified-selection/SelectionScope.js +156 -0
- package/lib/esm/unified-selection/SelectionScope.js.map +1 -0
- package/lib/esm/unified-selection/SelectionStorage.d.ts +16 -3
- package/lib/esm/unified-selection/SelectionStorage.d.ts.map +1 -1
- package/lib/esm/unified-selection/SelectionStorage.js +13 -2
- package/lib/esm/unified-selection/SelectionStorage.js.map +1 -1
- package/lib/esm/unified-selection/queries/ECMetadata.d.ts +44 -0
- package/lib/esm/unified-selection/queries/ECMetadata.d.ts.map +1 -0
- package/lib/esm/unified-selection/queries/ECMetadata.js +13 -0
- package/lib/esm/unified-selection/queries/ECMetadata.js.map +1 -0
- package/lib/esm/unified-selection/queries/ECSqlCore.d.ts +69 -0
- package/lib/esm/unified-selection/queries/ECSqlCore.d.ts.map +1 -0
- package/lib/esm/unified-selection/queries/ECSqlCore.js +19 -0
- package/lib/esm/unified-selection/queries/ECSqlCore.js.map +1 -0
- package/lib/esm/unified-selection.d.ts +4 -1
- package/lib/esm/unified-selection.d.ts.map +1 -1
- package/lib/esm/unified-selection.js +4 -1
- package/lib/esm/unified-selection.js.map +1 -1
- package/package.json +9 -3
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*---------------------------------------------------------------------------------------------
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.formIdBindings = void 0;
|
|
8
|
+
/**
|
|
9
|
+
* Forms ECSql bindings from given ID's.
|
|
10
|
+
*/
|
|
11
|
+
function formIdBindings(property, ids, bindings) {
|
|
12
|
+
if (ids.length > 1000) {
|
|
13
|
+
bindings.push({ type: "idset", value: ids });
|
|
14
|
+
return `InVirtualSet(?, ${property})`;
|
|
15
|
+
}
|
|
16
|
+
if (ids.length === 0) {
|
|
17
|
+
return `FALSE`;
|
|
18
|
+
}
|
|
19
|
+
ids.forEach((id) => bindings.push({ type: "id", value: id }));
|
|
20
|
+
return `${property} IN (${ids.map(() => "?").join(",")})`;
|
|
21
|
+
}
|
|
22
|
+
exports.formIdBindings = formIdBindings;
|
|
23
|
+
//# sourceMappingURL=ECSqlCore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ECSqlCore.js","sourceRoot":"","sources":["../../../../src/unified-selection/queries/ECSqlCore.ts"],"names":[],"mappings":";AAAA;;;gGAGgG;;;AAyEhG;;GAEG;AACH,SAAgB,cAAc,CAAC,QAAgB,EAAE,GAAa,EAAE,QAAwB;IACtF,IAAI,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE;QACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7C,OAAO,mBAAmB,QAAQ,GAAG,CAAC;KACvC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE;QACpB,OAAO,OAAO,CAAC;KAChB;IAED,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IAC9D,OAAO,GAAG,QAAQ,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AAC5D,CAAC;AAZD,wCAYC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\n/**\n * Types of values that can be bound to an ECSql query.\n */\nexport type ECSqlBindingType = \"boolean\" | \"double\" | \"id\" | \"idset\" | \"int\" | \"long\" | \"string\" | \"point2d\" | \"point3d\";\n\n/**\n * Defines an ECSql binding consisting of a value and its type. Necessary to differentiate between numeric\n * types and `Id64String` vs `string`.\n */\nexport type ECSqlBinding =\n | {\n type: \"boolean\";\n value?: boolean;\n }\n | {\n type: \"double\" | \"int\" | \"long\";\n value?: number;\n }\n | {\n type: \"id\";\n value?: string;\n }\n | {\n type: \"idset\";\n value?: string[];\n }\n | {\n type: \"string\";\n value?: string;\n }\n | {\n type: \"point2d\";\n value?: { x: number; y: number };\n }\n | {\n type: \"point3d\";\n value?: { x: number; y: number; z: number };\n };\n\n/**\n * Defines requested ECSQL result row format.\n */\nexport type ECSqlQueryRowFormat = \"ECSqlPropertyNames\" | \"Indexes\";\n\n/**\n * Defines options for ECSQL query reader.\n */\nexport interface ECSqlQueryReaderOptions {\n rowFormat?: ECSqlQueryRowFormat;\n}\n\n/**\n * Represents a single row of an ECSQL query result.\n */\nexport interface ECSqlQueryRow {\n [propertyName: string]: any;\n [propertyIndex: number]: any;\n}\n\n/**\n * Represents ECSQL query results reader.\n */\nexport type ECSqlQueryReader = AsyncIterableIterator<ECSqlQueryRow>;\n\n/**\n * An interface for something that knows how to create an ECSQL query reader.\n */\nexport interface IECSqlQueryExecutor {\n createQueryReader(ecsql: string, bindings?: ECSqlBinding[], config?: ECSqlQueryReaderOptions): ECSqlQueryReader;\n}\n\n/**\n * Forms ECSql bindings from given ID's.\n */\nexport function formIdBindings(property: string, ids: string[], bindings: ECSqlBinding[]): string {\n if (ids.length > 1000) {\n bindings.push({ type: \"idset\", value: ids });\n return `InVirtualSet(?, ${property})`;\n }\n\n if (ids.length === 0) {\n return `FALSE`;\n }\n\n ids.forEach((id) => bindings.push({ type: \"id\", value: id }));\n return `${property} IN (${ids.map(() => \"?\").join(\",\")})`;\n}\n"]}
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* API for working with unified selection.
|
|
6
6
|
*/
|
|
7
7
|
export * from "./unified-selection/Selectable";
|
|
8
|
-
export
|
|
8
|
+
export { SelectionStorage, createStorage } from "./unified-selection/SelectionStorage";
|
|
9
|
+
export { createHiliteSetProvider, HiliteSet, HiliteSetProvider } from "./unified-selection/HiliteSetProvider";
|
|
10
|
+
export { createCachingHiliteSetProvider, CachingHiliteSetProvider } from "./unified-selection/CachingHiliteSetProvider";
|
|
11
|
+
export { computeSelection } from "./unified-selection/SelectionScope";
|
|
9
12
|
export { StorageSelectionChangeType, StorageSelectionChangeEventArgs, StorageSelectionChangesListener, SelectionChangeEvent, } from "./unified-selection/SelectionChangeEvent";
|
|
10
13
|
//# sourceMappingURL=unified-selection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unified-selection.d.ts","sourceRoot":"","sources":["../../src/unified-selection.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,cAAc,gCAAgC,CAAC;AAC/C,
|
|
1
|
+
{"version":3,"file":"unified-selection.d.ts","sourceRoot":"","sources":["../../src/unified-selection.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,cAAc,gCAAgC,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACvF,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AAC9G,OAAO,EAAE,8BAA8B,EAAE,wBAAwB,EAAE,MAAM,8CAA8C,CAAC;AACxH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EACL,0BAA0B,EAC1B,+BAA+B,EAC/B,+BAA+B,EAC/B,oBAAoB,GACrB,MAAM,0CAA0C,CAAC"}
|
|
@@ -18,6 +18,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
18
18
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.computeSelection = exports.createCachingHiliteSetProvider = exports.createHiliteSetProvider = exports.createStorage = void 0;
|
|
21
22
|
/**
|
|
22
23
|
* @module UnifiedSelection
|
|
23
24
|
*
|
|
@@ -25,5 +26,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
25
26
|
* API for working with unified selection.
|
|
26
27
|
*/
|
|
27
28
|
__exportStar(require("./unified-selection/Selectable"), exports);
|
|
28
|
-
|
|
29
|
+
var SelectionStorage_1 = require("./unified-selection/SelectionStorage");
|
|
30
|
+
Object.defineProperty(exports, "createStorage", { enumerable: true, get: function () { return SelectionStorage_1.createStorage; } });
|
|
31
|
+
var HiliteSetProvider_1 = require("./unified-selection/HiliteSetProvider");
|
|
32
|
+
Object.defineProperty(exports, "createHiliteSetProvider", { enumerable: true, get: function () { return HiliteSetProvider_1.createHiliteSetProvider; } });
|
|
33
|
+
var CachingHiliteSetProvider_1 = require("./unified-selection/CachingHiliteSetProvider");
|
|
34
|
+
Object.defineProperty(exports, "createCachingHiliteSetProvider", { enumerable: true, get: function () { return CachingHiliteSetProvider_1.createCachingHiliteSetProvider; } });
|
|
35
|
+
var SelectionScope_1 = require("./unified-selection/SelectionScope");
|
|
36
|
+
Object.defineProperty(exports, "computeSelection", { enumerable: true, get: function () { return SelectionScope_1.computeSelection; } });
|
|
29
37
|
//# sourceMappingURL=unified-selection.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unified-selection.js","sourceRoot":"","sources":["../../src/unified-selection.ts"],"names":[],"mappings":";AAAA;;;gGAGgG
|
|
1
|
+
{"version":3,"file":"unified-selection.js","sourceRoot":"","sources":["../../src/unified-selection.ts"],"names":[],"mappings":";AAAA;;;gGAGgG;;;;;;;;;;;;;;;;;AAEhG;;;;;GAKG;AACH,iEAA+C;AAC/C,yEAAuF;AAA5D,iHAAA,aAAa,OAAA;AACxC,2EAA8G;AAArG,4HAAA,uBAAuB,OAAA;AAChC,yFAAwH;AAA/G,0IAAA,8BAA8B,OAAA;AACvC,qEAAsE;AAA7D,kHAAA,gBAAgB,OAAA","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\n/**\n * @module UnifiedSelection\n *\n * @docs-group-description UnifiedSelection\n * API for working with unified selection.\n */\nexport * from \"./unified-selection/Selectable\";\nexport { SelectionStorage, createStorage } from \"./unified-selection/SelectionStorage\";\nexport { createHiliteSetProvider, HiliteSet, HiliteSetProvider } from \"./unified-selection/HiliteSetProvider\";\nexport { createCachingHiliteSetProvider, CachingHiliteSetProvider } from \"./unified-selection/CachingHiliteSetProvider\";\nexport { computeSelection } from \"./unified-selection/SelectionScope\";\nexport {\n StorageSelectionChangeType,\n StorageSelectionChangeEventArgs,\n StorageSelectionChangesListener,\n SelectionChangeEvent,\n} from \"./unified-selection/SelectionChangeEvent\";\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { HiliteSet } from "./HiliteSetProvider";
|
|
2
|
+
import { IMetadataProvider } from "./queries/ECMetadata";
|
|
3
|
+
import { IECSqlQueryExecutor } from "./queries/ECSqlCore";
|
|
4
|
+
import { SelectionStorage } from "./SelectionStorage";
|
|
5
|
+
/**
|
|
6
|
+
* Props for creating a `CachingHiliteSetProvider` instance.
|
|
7
|
+
* @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.
|
|
8
|
+
*/
|
|
9
|
+
export interface CachingHiliteSetProviderProps {
|
|
10
|
+
selectionStorage: SelectionStorage;
|
|
11
|
+
iModelProvider: (iModelKey: string) => {
|
|
12
|
+
queryExecutor: IECSqlQueryExecutor;
|
|
13
|
+
metadataProvider: IMetadataProvider;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Defines return value of `createCachingHiliteSetProvider`.
|
|
18
|
+
*
|
|
19
|
+
* @beta Used in public API as a return value. Not expected to be created / extended by package
|
|
20
|
+
* consumers, may be supplemented with required attributes any time.
|
|
21
|
+
*/
|
|
22
|
+
export interface CachingHiliteSetProvider {
|
|
23
|
+
/** Get the current hilite set iterator for the specified imodel */
|
|
24
|
+
getHiliteSet(props: {
|
|
25
|
+
/** iModel to get hilite set for */
|
|
26
|
+
iModelKey: string;
|
|
27
|
+
}): AsyncIterableIterator<HiliteSet>;
|
|
28
|
+
/** Disposes the cache. */
|
|
29
|
+
dispose(): void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a hilite set provider that caches hilite set for current selection for given iModel so any subsequent
|
|
33
|
+
* hilite set requests for the same iModel don't cost until selection in given selection storage changes.
|
|
34
|
+
* @beta
|
|
35
|
+
*/
|
|
36
|
+
export declare function createCachingHiliteSetProvider(props: CachingHiliteSetProviderProps): CachingHiliteSetProvider;
|
|
37
|
+
//# sourceMappingURL=CachingHiliteSetProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CachingHiliteSetProvider.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/CachingHiliteSetProvider.ts"],"names":[],"mappings":"AAWA,OAAO,EAA2B,SAAS,EAAqB,MAAM,qBAAqB,CAAC;AAC5F,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAuC,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3F;;;GAGG;AACH,MAAM,WAAW,6BAA6B;IAC5C,gBAAgB,EAAE,gBAAgB,CAAC;IACnC,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK;QAAE,aAAa,EAAE,mBAAmB,CAAC;QAAC,gBAAgB,EAAE,iBAAiB,CAAA;KAAE,CAAC;CACpH;AAED;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,mEAAmE;IACnE,YAAY,CAAC,KAAK,EAAE;QAClB,mCAAmC;QACnC,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAErC,0BAA0B;IAC1B,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,6BAA6B,GAAG,wBAAwB,CAE7G"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
/** @packageDocumentation
|
|
6
|
+
* @module UnifiedSelection
|
|
7
|
+
*/
|
|
8
|
+
import { from, shareReplay } from "rxjs";
|
|
9
|
+
import { eachValueFrom } from "rxjs-for-await";
|
|
10
|
+
import { createHiliteSetProvider } from "./HiliteSetProvider";
|
|
11
|
+
import { IMODEL_CLOSE_SELECTION_CLEAR_SOURCE } from "./SelectionStorage";
|
|
12
|
+
/**
|
|
13
|
+
* Creates a hilite set provider that caches hilite set for current selection for given iModel so any subsequent
|
|
14
|
+
* hilite set requests for the same iModel don't cost until selection in given selection storage changes.
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
export function createCachingHiliteSetProvider(props) {
|
|
18
|
+
return new CachingHiliteSetProviderImpl(props);
|
|
19
|
+
}
|
|
20
|
+
class CachingHiliteSetProviderImpl {
|
|
21
|
+
_selectionStorage;
|
|
22
|
+
_hiliteSetProviders = new Map();
|
|
23
|
+
_cache = new Map();
|
|
24
|
+
_removeListener;
|
|
25
|
+
_iModelProvider;
|
|
26
|
+
constructor(props) {
|
|
27
|
+
this._selectionStorage = props.selectionStorage;
|
|
28
|
+
this._iModelProvider = props.iModelProvider;
|
|
29
|
+
this._removeListener = this._selectionStorage.selectionChangeEvent.addListener((args) => {
|
|
30
|
+
this._cache.delete(args.iModelKey);
|
|
31
|
+
if (args.changeType === "clear" && args.source === IMODEL_CLOSE_SELECTION_CLEAR_SOURCE) {
|
|
32
|
+
this._hiliteSetProviders.delete(args.iModelKey);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
getHiliteSet({ iModelKey }) {
|
|
37
|
+
const { queryExecutor, metadataProvider } = this._iModelProvider(iModelKey);
|
|
38
|
+
const provider = this.getHiliteSetProvider(iModelKey, queryExecutor, metadataProvider);
|
|
39
|
+
let hiliteSet = this._cache.get(iModelKey);
|
|
40
|
+
if (!hiliteSet) {
|
|
41
|
+
const selectables = this._selectionStorage.getSelection({ iModelKey });
|
|
42
|
+
hiliteSet = from(provider.getHiliteSet({ selectables })).pipe(shareReplay({ refCount: true }));
|
|
43
|
+
this._cache.set(iModelKey, hiliteSet);
|
|
44
|
+
}
|
|
45
|
+
return eachValueFrom(hiliteSet);
|
|
46
|
+
}
|
|
47
|
+
dispose() {
|
|
48
|
+
this._removeListener();
|
|
49
|
+
this._hiliteSetProviders = new Map();
|
|
50
|
+
this._cache = new Map();
|
|
51
|
+
}
|
|
52
|
+
getHiliteSetProvider(iModelKey, queryExecutor, metadataProvider) {
|
|
53
|
+
let provider = this._hiliteSetProviders.get(iModelKey);
|
|
54
|
+
if (!provider) {
|
|
55
|
+
provider = createHiliteSetProvider({ queryExecutor, metadataProvider });
|
|
56
|
+
this._hiliteSetProviders.set(iModelKey, provider);
|
|
57
|
+
}
|
|
58
|
+
return provider;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=CachingHiliteSetProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CachingHiliteSetProvider.js","sourceRoot":"","sources":["../../../src/unified-selection/CachingHiliteSetProvider.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG;;GAEG;AAEH,OAAO,EAAE,IAAI,EAAc,WAAW,EAAE,MAAM,MAAM,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,uBAAuB,EAAgC,MAAM,qBAAqB,CAAC;AAI5F,OAAO,EAAE,mCAAmC,EAAoB,MAAM,oBAAoB,CAAC;AA4B3F;;;;GAIG;AACH,MAAM,UAAU,8BAA8B,CAAC,KAAoC;IACjF,OAAO,IAAI,4BAA4B,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,4BAA4B;IACxB,iBAAiB,CAAmB;IACpC,mBAAmB,GAAG,IAAI,GAAG,EAA6B,CAAC;IAC3D,MAAM,GAAG,IAAI,GAAG,EAAiC,CAAC;IAClD,eAAe,CAAa;IAC5B,eAAe,CAAqG;IAE5H,YAAY,KAAoC;QAC9C,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,gBAAgB,CAAC;QAChD,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC;QAC5C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC,IAAqC,EAAE,EAAE;YACvH,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACnC,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO,IAAI,IAAI,CAAC,MAAM,KAAK,mCAAmC,EAAE;gBACtF,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aACjD;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEM,YAAY,CAAC,EAAE,SAAS,EAAyB;QACtD,MAAM,EAAE,aAAa,EAAE,gBAAgB,EAAE,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAC,SAAS,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC;QACvF,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAE3C,IAAI,CAAC,SAAS,EAAE;YACd,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;YACvE,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC/F,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;SACvC;QAED,OAAO,aAAa,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAEM,OAAO;QACZ,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,IAAI,CAAC,mBAAmB,GAAG,IAAI,GAAG,EAAE,CAAC;QACrC,IAAI,CAAC,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;IAC1B,CAAC;IAEO,oBAAoB,CAAC,SAAiB,EAAE,aAAkC,EAAE,gBAAmC;QACrH,IAAI,QAAQ,GAAG,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,EAAE;YACb,QAAQ,GAAG,uBAAuB,CAAC,EAAE,aAAa,EAAE,gBAAgB,EAAE,CAAC,CAAC;YACxE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;SACnD;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module UnifiedSelection\n */\n\nimport { from, Observable, shareReplay } from \"rxjs\";\nimport { eachValueFrom } from \"rxjs-for-await\";\nimport { createHiliteSetProvider, HiliteSet, HiliteSetProvider } from \"./HiliteSetProvider\";\nimport { IMetadataProvider } from \"./queries/ECMetadata\";\nimport { IECSqlQueryExecutor } from \"./queries/ECSqlCore\";\nimport { StorageSelectionChangeEventArgs } from \"./SelectionChangeEvent\";\nimport { IMODEL_CLOSE_SELECTION_CLEAR_SOURCE, SelectionStorage } from \"./SelectionStorage\";\n\n/**\n * Props for creating a `CachingHiliteSetProvider` instance.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.\n */\nexport interface CachingHiliteSetProviderProps {\n selectionStorage: SelectionStorage;\n iModelProvider: (iModelKey: string) => { queryExecutor: IECSqlQueryExecutor; metadataProvider: IMetadataProvider };\n}\n\n/**\n * Defines return value of `createCachingHiliteSetProvider`.\n *\n * @beta Used in public API as a return value. Not expected to be created / extended by package\n * consumers, may be supplemented with required attributes any time.\n */\nexport interface CachingHiliteSetProvider {\n /** Get the current hilite set iterator for the specified imodel */\n getHiliteSet(props: {\n /** iModel to get hilite set for */\n iModelKey: string;\n }): AsyncIterableIterator<HiliteSet>;\n\n /** Disposes the cache. */\n dispose(): void;\n}\n\n/**\n * Creates a hilite set provider that caches hilite set for current selection for given iModel so any subsequent\n * hilite set requests for the same iModel don't cost until selection in given selection storage changes.\n * @beta\n */\nexport function createCachingHiliteSetProvider(props: CachingHiliteSetProviderProps): CachingHiliteSetProvider {\n return new CachingHiliteSetProviderImpl(props);\n}\n\nclass CachingHiliteSetProviderImpl implements CachingHiliteSetProvider {\n private _selectionStorage: SelectionStorage;\n private _hiliteSetProviders = new Map<string, HiliteSetProvider>();\n private _cache = new Map<string, Observable<HiliteSet>>();\n private _removeListener: () => void;\n private _iModelProvider: (iModelKey: string) => { queryExecutor: IECSqlQueryExecutor; metadataProvider: IMetadataProvider };\n\n constructor(props: CachingHiliteSetProviderProps) {\n this._selectionStorage = props.selectionStorage;\n this._iModelProvider = props.iModelProvider;\n this._removeListener = this._selectionStorage.selectionChangeEvent.addListener((args: StorageSelectionChangeEventArgs) => {\n this._cache.delete(args.iModelKey);\n if (args.changeType === \"clear\" && args.source === IMODEL_CLOSE_SELECTION_CLEAR_SOURCE) {\n this._hiliteSetProviders.delete(args.iModelKey);\n }\n });\n }\n\n public getHiliteSet({ iModelKey }: { iModelKey: string }): AsyncIterableIterator<HiliteSet> {\n const { queryExecutor, metadataProvider } = this._iModelProvider(iModelKey);\n const provider = this.getHiliteSetProvider(iModelKey, queryExecutor, metadataProvider);\n let hiliteSet = this._cache.get(iModelKey);\n\n if (!hiliteSet) {\n const selectables = this._selectionStorage.getSelection({ iModelKey });\n hiliteSet = from(provider.getHiliteSet({ selectables })).pipe(shareReplay({ refCount: true }));\n this._cache.set(iModelKey, hiliteSet);\n }\n\n return eachValueFrom(hiliteSet);\n }\n\n public dispose(): void {\n this._removeListener();\n this._hiliteSetProviders = new Map();\n this._cache = new Map();\n }\n\n private getHiliteSetProvider(iModelKey: string, queryExecutor: IECSqlQueryExecutor, metadataProvider: IMetadataProvider) {\n let provider = this._hiliteSetProviders.get(iModelKey);\n if (!provider) {\n provider = createHiliteSetProvider({ queryExecutor, metadataProvider });\n this._hiliteSetProviders.set(iModelKey, provider);\n }\n return provider;\n }\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { IMetadataProvider } from "./queries/ECMetadata";
|
|
2
|
+
import { IECSqlQueryExecutor } from "./queries/ECSqlCore";
|
|
3
|
+
import { Selectables } from "./Selectable";
|
|
4
|
+
/**
|
|
5
|
+
* A set of model, subcategory and element ids that can be used for specifying hilite.
|
|
6
|
+
* @see https://www.itwinjs.org/reference/core-frontend/selectionset/hiliteset/
|
|
7
|
+
* @beta
|
|
8
|
+
*/
|
|
9
|
+
export interface HiliteSet {
|
|
10
|
+
models: string[];
|
|
11
|
+
subCategories: string[];
|
|
12
|
+
elements: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Props for creating a `HiliteSetProvider` instance.
|
|
16
|
+
* @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.
|
|
17
|
+
*/
|
|
18
|
+
export interface HiliteSetProviderProps {
|
|
19
|
+
queryExecutor: IECSqlQueryExecutor;
|
|
20
|
+
metadataProvider: IMetadataProvider;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Defines return value of `createHiliteSetProvider`.
|
|
24
|
+
*
|
|
25
|
+
* @beta Used in public API as a return value. Not expected to be created / extended by package
|
|
26
|
+
* consumers, may be supplemented with required attributes any time.
|
|
27
|
+
*/
|
|
28
|
+
export interface HiliteSetProvider {
|
|
29
|
+
/** Get the current hilite set iterator for the specified imodel */
|
|
30
|
+
getHiliteSet(props: {
|
|
31
|
+
selectables: Selectables;
|
|
32
|
+
}): AsyncIterableIterator<HiliteSet>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a hilite set provider that returns a `HiliteSet` for given selectables.
|
|
36
|
+
* @beta
|
|
37
|
+
*/
|
|
38
|
+
export declare function createHiliteSetProvider(props: HiliteSetProviderProps): HiliteSetProvider;
|
|
39
|
+
//# sourceMappingURL=HiliteSetProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HiliteSetProvider.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/HiliteSetProvider.ts"],"names":[],"mappings":"AAWA,OAAO,EAAW,iBAAiB,EAAsB,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAgC,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAyB,WAAW,EAAE,MAAM,cAAc,CAAC;AAIlE;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,mBAAmB,CAAC;IACnC,gBAAgB,EAAE,iBAAiB,CAAC;CACrC;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,YAAY,CAAC,KAAK,EAAE;QAAE,WAAW,EAAE,WAAW,CAAA;KAAE,GAAG,qBAAqB,CAAC,SAAS,CAAC,CAAC;CACrF;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,sBAAsB,GAAG,iBAAiB,CAExF"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
/** @packageDocumentation
|
|
6
|
+
* @module UnifiedSelection
|
|
7
|
+
*/
|
|
8
|
+
import { EMPTY, filter, forkJoin, from, map, merge, mergeMap, scan, shareReplay, Subject, toArray } from "rxjs";
|
|
9
|
+
import { eachValueFrom } from "rxjs-for-await";
|
|
10
|
+
import { parseFullClassName } from "./queries/ECMetadata";
|
|
11
|
+
import { formIdBindings } from "./queries/ECSqlCore";
|
|
12
|
+
const HILITE_SET_EMIT_FREQUENCY = 20;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a hilite set provider that returns a `HiliteSet` for given selectables.
|
|
15
|
+
* @beta
|
|
16
|
+
*/
|
|
17
|
+
export function createHiliteSetProvider(props) {
|
|
18
|
+
return new HiliteSetProviderImpl(props);
|
|
19
|
+
}
|
|
20
|
+
class HiliteSetProviderImpl {
|
|
21
|
+
_queryExecutor;
|
|
22
|
+
_metadataProvider;
|
|
23
|
+
// Map between a class name and its type
|
|
24
|
+
_classRelationCache;
|
|
25
|
+
constructor(props) {
|
|
26
|
+
this._queryExecutor = props.queryExecutor;
|
|
27
|
+
this._metadataProvider = props.metadataProvider;
|
|
28
|
+
this._classRelationCache = new Map();
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Get hilite set iterator for supplied `Selectables`.
|
|
32
|
+
*/
|
|
33
|
+
getHiliteSet(props) {
|
|
34
|
+
const obs = this.getHiliteSetObservable(props);
|
|
35
|
+
return eachValueFrom(obs);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Returns a "hot" observable of hilite sets.
|
|
39
|
+
*/
|
|
40
|
+
getHiliteSetObservable({ selectables }) {
|
|
41
|
+
const instancesByType = this.getInstancesByType(selectables);
|
|
42
|
+
const observables = {
|
|
43
|
+
models: this.getHilitedModels(instancesByType),
|
|
44
|
+
subCategories: this.getHilitedSubCategories(instancesByType),
|
|
45
|
+
elements: this.getHilitedElements(instancesByType),
|
|
46
|
+
};
|
|
47
|
+
let hiliteSet = { models: [], subCategories: [], elements: [] };
|
|
48
|
+
let lastEmitTime = performance.now();
|
|
49
|
+
const subject = new Subject();
|
|
50
|
+
const subscriptions = ["models", "subCategories", "elements"].map((key) => observables[key].subscribe({
|
|
51
|
+
next(val) {
|
|
52
|
+
hiliteSet[key].push(val);
|
|
53
|
+
if (performance.now() - lastEmitTime < HILITE_SET_EMIT_FREQUENCY) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
subject.next(hiliteSet);
|
|
57
|
+
hiliteSet = { models: [], subCategories: [], elements: [] };
|
|
58
|
+
lastEmitTime = performance.now();
|
|
59
|
+
},
|
|
60
|
+
complete() {
|
|
61
|
+
observables[key] = undefined;
|
|
62
|
+
if (observables.models || observables.subCategories || observables.elements) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// Emit last batch before completing the observable.
|
|
66
|
+
if (hiliteSet.elements.length || hiliteSet.models.length || hiliteSet.subCategories.length) {
|
|
67
|
+
subject.next(hiliteSet);
|
|
68
|
+
}
|
|
69
|
+
subject.complete();
|
|
70
|
+
},
|
|
71
|
+
error(err) {
|
|
72
|
+
subscriptions.forEach((x) => x.unsubscribe());
|
|
73
|
+
subscriptions.length = 0;
|
|
74
|
+
subject.error(err);
|
|
75
|
+
},
|
|
76
|
+
}));
|
|
77
|
+
return subject;
|
|
78
|
+
}
|
|
79
|
+
async getType(key) {
|
|
80
|
+
const cachedType = this._classRelationCache.get(key.className.replace(".", ":"));
|
|
81
|
+
if (cachedType) {
|
|
82
|
+
return cachedType;
|
|
83
|
+
}
|
|
84
|
+
const promise = this.getTypeImpl(key).then((res) => {
|
|
85
|
+
// Update the cache with the result of the promise.
|
|
86
|
+
this._classRelationCache.set(key.className, res);
|
|
87
|
+
return res;
|
|
88
|
+
});
|
|
89
|
+
// Add the promise to cache to prevent `getTypeImpl` being called multiple times.
|
|
90
|
+
this._classRelationCache.set(key.className, promise);
|
|
91
|
+
return promise;
|
|
92
|
+
}
|
|
93
|
+
async getTypeImpl(key) {
|
|
94
|
+
const keyClass = await this.getClass(key.className);
|
|
95
|
+
return ((keyClass &&
|
|
96
|
+
((await this.checkType(keyClass, "BisCore", "Subject", "subject")) ??
|
|
97
|
+
(await this.checkType(keyClass, "BisCore", "Model", "model")) ??
|
|
98
|
+
(await this.checkType(keyClass, "BisCore", "Category", "category")) ??
|
|
99
|
+
(await this.checkType(keyClass, "BisCore", "SubCategory", "subCategory")) ??
|
|
100
|
+
(await this.checkType(keyClass, "Functional", "FunctionalElement", "functionalElement")) ??
|
|
101
|
+
(await this.checkType(keyClass, "BisCore", "GroupInformationElement", "groupInformationElement")) ??
|
|
102
|
+
(await this.checkType(keyClass, "BisCore", "GeometricElement", "geometricElement")) ??
|
|
103
|
+
(await this.checkType(keyClass, "BisCore", "Element", "element")))) ??
|
|
104
|
+
"unknown");
|
|
105
|
+
}
|
|
106
|
+
async checkType(keyClass, schemaName, className, type) {
|
|
107
|
+
return (await keyClass.is(className, schemaName)) ? type : undefined;
|
|
108
|
+
}
|
|
109
|
+
getInstancesByType(selectables) {
|
|
110
|
+
const keyTypeObs = merge(from(selectables.custom.values()).pipe(mergeMap((selectable) => selectable.loadInstanceKeys())), from(selectables.instanceKeys).pipe(mergeMap(([className, idSet]) => from(idSet).pipe(map((id) => ({ className, id })))))).pipe(
|
|
111
|
+
// Get types for each instance key
|
|
112
|
+
mergeMap((instanceKey) => from(this.getType(instanceKey)).pipe(map((instanceIdType) => ({ instanceId: instanceKey.id, instanceIdType })))),
|
|
113
|
+
// Cache the results
|
|
114
|
+
shareReplay());
|
|
115
|
+
return Object.fromEntries(INSTANCE_TYPES.map((type) => [
|
|
116
|
+
type,
|
|
117
|
+
keyTypeObs.pipe(filter(({ instanceIdType }) => instanceIdType === type), map(({ instanceId }) => instanceId), unique()),
|
|
118
|
+
]));
|
|
119
|
+
}
|
|
120
|
+
getHilitedModels(instancesByType) {
|
|
121
|
+
return forkJoin({
|
|
122
|
+
modelKeys: instancesByType.model.pipe(toArray()),
|
|
123
|
+
subjectKeys: instancesByType.subject.pipe(toArray()),
|
|
124
|
+
}).pipe(mergeMap(({ modelKeys, subjectKeys }) => {
|
|
125
|
+
if (!modelKeys.length && !subjectKeys.length) {
|
|
126
|
+
return EMPTY;
|
|
127
|
+
}
|
|
128
|
+
const bindings = [];
|
|
129
|
+
const query = `WITH RECURSIVE
|
|
130
|
+
ChildSubjects (ECInstanceId, JsonProperties) AS (
|
|
131
|
+
SELECT ECInstanceId, JsonProperties FROM BisCore.Subject WHERE ${formIdBindings("ECInstanceId", subjectKeys, bindings)}
|
|
132
|
+
UNION ALL
|
|
133
|
+
SELECT r.ECInstanceId, r.JsonProperties FROM ChildSubjects s
|
|
134
|
+
JOIN BisCore.Subject r ON r.Parent.Id = s.ECInstanceId
|
|
135
|
+
),
|
|
136
|
+
Models (ECInstanceId) AS (
|
|
137
|
+
SELECT s.ECInstanceId as \`ECInstanceId\` FROM BisCore.Model s
|
|
138
|
+
WHERE ${formIdBindings("ECInstanceId", modelKeys, bindings)}
|
|
139
|
+
)
|
|
140
|
+
SELECT r.ECInstanceId as \`ECInstanceId\` FROM ChildSubjects s
|
|
141
|
+
JOIN BisCore.PhysicalPartition r
|
|
142
|
+
ON r.Parent.Id = s.ECInstanceId
|
|
143
|
+
OR json_extract(s.JsonProperties,'$.Subject.Model.TargetPartition') = printf('0x%x', r.ECInstanceId)
|
|
144
|
+
UNION
|
|
145
|
+
SELECT ECInstanceId FROM Models;`;
|
|
146
|
+
return from(this._queryExecutor.createQueryReader(query, bindings));
|
|
147
|
+
}), map((row) => row.ECInstanceId));
|
|
148
|
+
}
|
|
149
|
+
getHilitedSubCategories(instancesByType) {
|
|
150
|
+
return forkJoin({
|
|
151
|
+
subCategoryKeys: instancesByType.subCategory.pipe(toArray()),
|
|
152
|
+
categoryKeys: instancesByType.category.pipe(toArray()),
|
|
153
|
+
}).pipe(mergeMap(({ subCategoryKeys, categoryKeys }) => {
|
|
154
|
+
if (!subCategoryKeys.length && !categoryKeys.length) {
|
|
155
|
+
return EMPTY;
|
|
156
|
+
}
|
|
157
|
+
const bindings = [];
|
|
158
|
+
const query = `WITH
|
|
159
|
+
CategorySubCategories (ECInstanceId) AS (
|
|
160
|
+
SELECT r.ECInstanceId as \`ECInstanceId\` FROM BisCore.Category s
|
|
161
|
+
JOIN BisCore.SubCategory r ON r.Parent.Id = s.ECInstanceId
|
|
162
|
+
WHERE ${formIdBindings("s.ECInstanceId", categoryKeys, bindings)}
|
|
163
|
+
),
|
|
164
|
+
SubCategories (ECInstanceId) AS (
|
|
165
|
+
SELECT s.ECInstanceId as \`ECInstanceId\` FROM BisCore.SubCategory s
|
|
166
|
+
WHERE ${formIdBindings("s.ECInstanceId", subCategoryKeys, bindings)}
|
|
167
|
+
)
|
|
168
|
+
SELECT ECInstanceId FROM CategorySubCategories
|
|
169
|
+
UNION
|
|
170
|
+
SELECT ECInstanceId FROM SubCategories;`;
|
|
171
|
+
return from(this._queryExecutor.createQueryReader(query, bindings));
|
|
172
|
+
}), map((row) => row.ECInstanceId));
|
|
173
|
+
}
|
|
174
|
+
getHilitedElements(instancesByType) {
|
|
175
|
+
return forkJoin({
|
|
176
|
+
groupInformationElementKeys: instancesByType.groupInformationElement.pipe(toArray()),
|
|
177
|
+
geometricElementKeys: instancesByType.geometricElement.pipe(toArray()),
|
|
178
|
+
functionalElements: instancesByType.functionalElement.pipe(toArray()),
|
|
179
|
+
elementKeys: instancesByType.element.pipe(toArray()),
|
|
180
|
+
}).pipe(mergeMap(({ groupInformationElementKeys, geometricElementKeys, functionalElements, elementKeys }) => {
|
|
181
|
+
const hasFunctionalElements = !!functionalElements.length;
|
|
182
|
+
if (!groupInformationElementKeys.length && !geometricElementKeys.length && !elementKeys.length && !hasFunctionalElements) {
|
|
183
|
+
return EMPTY;
|
|
184
|
+
}
|
|
185
|
+
const bindings = [];
|
|
186
|
+
const query = `WITH RECURSIVE
|
|
187
|
+
${hasFunctionalElements ? this.getHilitedFunctionalElementsQuery(functionalElements, bindings) : ""}
|
|
188
|
+
GroupMembers (ECInstanceId, ECClassId) AS (
|
|
189
|
+
SELECT TargetECInstanceId, TargetECClassId FROM BisCore.ElementGroupsMembers
|
|
190
|
+
WHERE ${formIdBindings("SourceECInstanceId", groupInformationElementKeys, bindings)}
|
|
191
|
+
),
|
|
192
|
+
GroupGeometricElements (ECInstanceId, ECClassId) AS (
|
|
193
|
+
SELECT ECInstanceId, ECClassId FROM GroupMembers
|
|
194
|
+
UNION ALL
|
|
195
|
+
SELECT r.ECInstanceId, r.ECClassId FROM GroupGeometricElements s
|
|
196
|
+
JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
|
|
197
|
+
),
|
|
198
|
+
ElementGeometricElements (ECInstanceId, ECClassId) AS (
|
|
199
|
+
SELECT ECInstanceId, ECClassId FROM BisCore.Element WHERE ${formIdBindings("ECInstanceId", elementKeys, bindings)}
|
|
200
|
+
UNION ALL
|
|
201
|
+
SELECT r.ECInstanceId, r.ECClassId FROM ElementGeometricElements s
|
|
202
|
+
JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
|
|
203
|
+
),
|
|
204
|
+
GeometricElementGeometricElements (ECInstanceId, ECClassId) AS (
|
|
205
|
+
SELECT ECInstanceId, ECClassId FROM BisCore.GeometricElement WHERE ${formIdBindings("ECInstanceId", geometricElementKeys, bindings)}
|
|
206
|
+
UNION ALL
|
|
207
|
+
SELECT r.ECInstanceId, r.ECClassId FROM GeometricElementGeometricElements s
|
|
208
|
+
JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
|
|
209
|
+
)
|
|
210
|
+
${hasFunctionalElements
|
|
211
|
+
? `
|
|
212
|
+
SELECT ECInstanceId FROM FunctionalElementChildGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)
|
|
213
|
+
UNION
|
|
214
|
+
`
|
|
215
|
+
: ``}
|
|
216
|
+
SELECT ECInstanceId FROM GeometricElementGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)
|
|
217
|
+
UNION
|
|
218
|
+
SELECT ECInstanceId FROM GroupGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)
|
|
219
|
+
UNION
|
|
220
|
+
SELECT ECInstanceId FROM ElementGeometricElements WHERE ECClassId IS (BisCore.GeometricElement);`;
|
|
221
|
+
return from(this._queryExecutor.createQueryReader(query, bindings));
|
|
222
|
+
}), map((row) => row.ECInstanceId));
|
|
223
|
+
}
|
|
224
|
+
getHilitedFunctionalElementsQuery(functionalElements, bindings) {
|
|
225
|
+
return `ChildFunctionalElements (ECInstanceId, ECClassId) AS (
|
|
226
|
+
SELECT ECInstanceId, ECClassId FROM Functional.FunctionalElement WHERE ${formIdBindings("ECInstanceId", functionalElements, bindings)}
|
|
227
|
+
UNION ALL
|
|
228
|
+
SELECT r.ECInstanceId, r.ECClassId FROM ChildFunctionalElements s
|
|
229
|
+
JOIN Functional.FunctionalElement r ON r.Parent.Id = s.ECInstanceId
|
|
230
|
+
),
|
|
231
|
+
PhysicalElements (ECInstanceId, ECClassId) AS (
|
|
232
|
+
SELECT r.SourceECInstanceId, r.SourceECClassId FROM ChildFunctionalElements s
|
|
233
|
+
JOIN Functional.PhysicalElementFulfillsFunction r ON r.TargetECInstanceId = s.ECInstanceId
|
|
234
|
+
),
|
|
235
|
+
DrawingGraphicElements (ECInstanceId, ECClassId) AS (
|
|
236
|
+
SELECT r.SourceECInstanceId, r.SourceECClassId FROM ChildFunctionalElements s
|
|
237
|
+
JOIN Functional.DrawingGraphicRepresentsFunctionalElement r ON r.TargetECInstanceId = s.ECInstanceId
|
|
238
|
+
),
|
|
239
|
+
PhysicalElementGeometricElements (ECInstanceId, ECClassId) AS (
|
|
240
|
+
SELECT ECInstanceId, ECClassId FROM PhysicalElements
|
|
241
|
+
UNION ALL
|
|
242
|
+
SELECT r.ECInstanceId, r.ECClassId FROM PhysicalElementGeometricElements s
|
|
243
|
+
JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
|
|
244
|
+
),
|
|
245
|
+
DrawingGraphicElementGeometricElements (ECInstanceId, ECClassId) AS (
|
|
246
|
+
SELECT ECInstanceId, ECClassId FROM DrawingGraphicElements
|
|
247
|
+
UNION ALL
|
|
248
|
+
SELECT r.ECInstanceId, r.ECClassId FROM DrawingGraphicElementGeometricElements s
|
|
249
|
+
JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
|
|
250
|
+
),
|
|
251
|
+
FunctionalElementChildGeometricElements (ECInstanceId, ECClassId) AS (
|
|
252
|
+
SELECT ECInstanceId, ECClassId FROM PhysicalElementGeometricElements
|
|
253
|
+
UNION
|
|
254
|
+
SELECT ECInstanceId, ECClassId FROM DrawingGraphicElementGeometricElements
|
|
255
|
+
),`;
|
|
256
|
+
}
|
|
257
|
+
async getClass(fullClassName) {
|
|
258
|
+
const { schemaName, className } = parseFullClassName(fullClassName);
|
|
259
|
+
const schema = await this._metadataProvider.getSchema(schemaName);
|
|
260
|
+
if (!schema) {
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
const schemaClass = await schema.getClass(className);
|
|
264
|
+
if (!schemaClass) {
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
return schemaClass;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const INSTANCE_TYPES = [
|
|
271
|
+
"subject",
|
|
272
|
+
"model",
|
|
273
|
+
"category",
|
|
274
|
+
"subCategory",
|
|
275
|
+
"functionalElement",
|
|
276
|
+
"groupInformationElement",
|
|
277
|
+
"geometricElement",
|
|
278
|
+
"element",
|
|
279
|
+
"unknown",
|
|
280
|
+
];
|
|
281
|
+
function unique() {
|
|
282
|
+
return function (obs) {
|
|
283
|
+
return obs.pipe(scan((acc, val) => {
|
|
284
|
+
if (acc.set.has(val)) {
|
|
285
|
+
delete acc.val;
|
|
286
|
+
return acc;
|
|
287
|
+
}
|
|
288
|
+
acc.set.add(val);
|
|
289
|
+
acc.val = val;
|
|
290
|
+
return acc;
|
|
291
|
+
}, { set: new Set() }), map(({ val }) => val), filter((x) => !!x));
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=HiliteSetProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HiliteSetProvider.js","sourceRoot":"","sources":["../../../src/unified-selection/HiliteSetProvider.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\n/** @packageDocumentation\n * @module UnifiedSelection\n */\n\nimport { EMPTY, filter, forkJoin, from, map, merge, mergeMap, Observable, scan, shareReplay, Subject, toArray } from \"rxjs\";\nimport { eachValueFrom } from \"rxjs-for-await\";\nimport { ECClass, IMetadataProvider, parseFullClassName } from \"./queries/ECMetadata\";\nimport { ECSqlBinding, formIdBindings, IECSqlQueryExecutor } from \"./queries/ECSqlCore\";\nimport { SelectableInstanceKey, Selectables } from \"./Selectable\";\n\nconst HILITE_SET_EMIT_FREQUENCY = 20;\n\n/**\n * A set of model, subcategory and element ids that can be used for specifying hilite.\n * @see https://www.itwinjs.org/reference/core-frontend/selectionset/hiliteset/\n * @beta\n */\nexport interface HiliteSet {\n models: string[];\n subCategories: string[];\n elements: string[];\n}\n\n/**\n * Props for creating a `HiliteSetProvider` instance.\n * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.\n */\nexport interface HiliteSetProviderProps {\n queryExecutor: IECSqlQueryExecutor;\n metadataProvider: IMetadataProvider;\n}\n\n/**\n * Defines return value of `createHiliteSetProvider`.\n *\n * @beta Used in public API as a return value. Not expected to be created / extended by package\n * consumers, may be supplemented with required attributes any time.\n */\nexport interface HiliteSetProvider {\n /** Get the current hilite set iterator for the specified imodel */\n getHiliteSet(props: { selectables: Selectables }): AsyncIterableIterator<HiliteSet>;\n}\n\n/**\n * Creates a hilite set provider that returns a `HiliteSet` for given selectables.\n * @beta\n */\nexport function createHiliteSetProvider(props: HiliteSetProviderProps): HiliteSetProvider {\n return new HiliteSetProviderImpl(props);\n}\n\nclass HiliteSetProviderImpl implements HiliteSetProvider {\n private _queryExecutor: IECSqlQueryExecutor;\n private _metadataProvider: IMetadataProvider;\n // Map between a class name and its type\n private _classRelationCache: Map<string, InstanceIdType | Promise<InstanceIdType>>;\n\n constructor(props: HiliteSetProviderProps) {\n this._queryExecutor = props.queryExecutor;\n this._metadataProvider = props.metadataProvider;\n this._classRelationCache = new Map();\n }\n\n /**\n * Get hilite set iterator for supplied `Selectables`.\n */\n public getHiliteSet(props: { selectables: Selectables }): AsyncIterableIterator<HiliteSet> {\n const obs = this.getHiliteSetObservable(props);\n return eachValueFrom(obs);\n }\n\n /**\n * Returns a \"hot\" observable of hilite sets.\n */\n private getHiliteSetObservable({ selectables }: { selectables: Selectables }): Subject<HiliteSet> {\n const instancesByType = this.getInstancesByType(selectables);\n const observables: { [key in keyof HiliteSet]?: Observable<string> } = {\n models: this.getHilitedModels(instancesByType),\n subCategories: this.getHilitedSubCategories(instancesByType),\n elements: this.getHilitedElements(instancesByType),\n };\n\n let hiliteSet: HiliteSet = { models: [], subCategories: [], elements: [] };\n let lastEmitTime = performance.now();\n const subject = new Subject<HiliteSet>();\n const subscriptions = ([\"models\", \"subCategories\", \"elements\"] as const).map((key) =>\n observables[key]!.subscribe({\n next(val) {\n hiliteSet[key].push(val);\n if (performance.now() - lastEmitTime < HILITE_SET_EMIT_FREQUENCY) {\n return;\n }\n subject.next(hiliteSet);\n hiliteSet = { models: [], subCategories: [], elements: [] };\n lastEmitTime = performance.now();\n },\n complete() {\n observables[key] = undefined;\n if (observables.models || observables.subCategories || observables.elements) {\n return;\n }\n // Emit last batch before completing the observable.\n if (hiliteSet.elements.length || hiliteSet.models.length || hiliteSet.subCategories.length) {\n subject.next(hiliteSet);\n }\n subject.complete();\n },\n error(err) {\n subscriptions.forEach((x) => x.unsubscribe());\n subscriptions.length = 0;\n subject.error(err);\n },\n }),\n );\n\n return subject;\n }\n\n private async getType(key: SelectableInstanceKey): Promise<InstanceIdType> {\n const cachedType = this._classRelationCache.get(key.className.replace(\".\", \":\"));\n if (cachedType) {\n return cachedType;\n }\n\n const promise = this.getTypeImpl(key).then((res) => {\n // Update the cache with the result of the promise.\n this._classRelationCache.set(key.className, res);\n return res;\n });\n\n // Add the promise to cache to prevent `getTypeImpl` being called multiple times.\n this._classRelationCache.set(key.className, promise);\n return promise;\n }\n\n private async getTypeImpl(key: SelectableInstanceKey): Promise<InstanceIdType> {\n const keyClass = await this.getClass(key.className);\n return (\n (keyClass &&\n ((await this.checkType(keyClass, \"BisCore\", \"Subject\", \"subject\")) ??\n (await this.checkType(keyClass, \"BisCore\", \"Model\", \"model\")) ??\n (await this.checkType(keyClass, \"BisCore\", \"Category\", \"category\")) ??\n (await this.checkType(keyClass, \"BisCore\", \"SubCategory\", \"subCategory\")) ??\n (await this.checkType(keyClass, \"Functional\", \"FunctionalElement\", \"functionalElement\")) ??\n (await this.checkType(keyClass, \"BisCore\", \"GroupInformationElement\", \"groupInformationElement\")) ??\n (await this.checkType(keyClass, \"BisCore\", \"GeometricElement\", \"geometricElement\")) ??\n (await this.checkType(keyClass, \"BisCore\", \"Element\", \"element\")))) ??\n \"unknown\"\n );\n }\n\n private async checkType(keyClass: ECClass, schemaName: string, className: string, type: InstanceIdType) {\n return (await keyClass.is(className, schemaName)) ? type : undefined;\n }\n\n private getInstancesByType(selectables: Selectables): InstancesByType {\n const keyTypeObs = merge(\n from(selectables.custom.values()).pipe(mergeMap((selectable) => selectable.loadInstanceKeys())),\n from(selectables.instanceKeys).pipe(mergeMap(([className, idSet]) => from(idSet).pipe(map((id) => ({ className, id }))))),\n ).pipe(\n // Get types for each instance key\n mergeMap((instanceKey) => from(this.getType(instanceKey)).pipe(map((instanceIdType) => ({ instanceId: instanceKey.id, instanceIdType })))),\n // Cache the results\n shareReplay(),\n );\n\n return Object.fromEntries(\n INSTANCE_TYPES.map((type) => [\n type,\n keyTypeObs.pipe(\n filter(({ instanceIdType }) => instanceIdType === type),\n map(({ instanceId }) => instanceId),\n unique(),\n ),\n ]),\n ) as InstancesByType;\n }\n\n private getHilitedModels(instancesByType: InstancesByType): Observable<string> {\n return forkJoin({\n modelKeys: instancesByType.model.pipe(toArray()),\n subjectKeys: instancesByType.subject.pipe(toArray()),\n }).pipe(\n mergeMap(({ modelKeys, subjectKeys }) => {\n if (!modelKeys.length && !subjectKeys.length) {\n return EMPTY;\n }\n\n const bindings: ECSqlBinding[] = [];\n const query = `WITH RECURSIVE\n ChildSubjects (ECInstanceId, JsonProperties) AS (\n SELECT ECInstanceId, JsonProperties FROM BisCore.Subject WHERE ${formIdBindings(\"ECInstanceId\", subjectKeys, bindings)}\n UNION ALL\n SELECT r.ECInstanceId, r.JsonProperties FROM ChildSubjects s\n JOIN BisCore.Subject r ON r.Parent.Id = s.ECInstanceId\n ),\n Models (ECInstanceId) AS (\n SELECT s.ECInstanceId as \\`ECInstanceId\\` FROM BisCore.Model s\n WHERE ${formIdBindings(\"ECInstanceId\", modelKeys, bindings)}\n )\n SELECT r.ECInstanceId as \\`ECInstanceId\\` FROM ChildSubjects s\n JOIN BisCore.PhysicalPartition r\n ON r.Parent.Id = s.ECInstanceId\n OR json_extract(s.JsonProperties,'$.Subject.Model.TargetPartition') = printf('0x%x', r.ECInstanceId)\n UNION\n SELECT ECInstanceId FROM Models;`;\n return from(this._queryExecutor.createQueryReader(query, bindings));\n }),\n map((row) => row.ECInstanceId),\n );\n }\n\n private getHilitedSubCategories(instancesByType: InstancesByType): Observable<string> {\n return forkJoin({\n subCategoryKeys: instancesByType.subCategory.pipe(toArray()),\n categoryKeys: instancesByType.category.pipe(toArray()),\n }).pipe(\n mergeMap(({ subCategoryKeys, categoryKeys }) => {\n if (!subCategoryKeys.length && !categoryKeys.length) {\n return EMPTY;\n }\n\n const bindings: ECSqlBinding[] = [];\n const query = `WITH\n CategorySubCategories (ECInstanceId) AS (\n SELECT r.ECInstanceId as \\`ECInstanceId\\` FROM BisCore.Category s\n JOIN BisCore.SubCategory r ON r.Parent.Id = s.ECInstanceId\n WHERE ${formIdBindings(\"s.ECInstanceId\", categoryKeys, bindings)}\n ),\n SubCategories (ECInstanceId) AS (\n SELECT s.ECInstanceId as \\`ECInstanceId\\` FROM BisCore.SubCategory s\n WHERE ${formIdBindings(\"s.ECInstanceId\", subCategoryKeys, bindings)}\n )\n SELECT ECInstanceId FROM CategorySubCategories\n UNION\n SELECT ECInstanceId FROM SubCategories;`;\n return from(this._queryExecutor.createQueryReader(query, bindings));\n }),\n map((row) => row.ECInstanceId),\n );\n }\n\n private getHilitedElements(instancesByType: InstancesByType): Observable<string> {\n return forkJoin({\n groupInformationElementKeys: instancesByType.groupInformationElement.pipe(toArray()),\n geometricElementKeys: instancesByType.geometricElement.pipe(toArray()),\n functionalElements: instancesByType.functionalElement.pipe(toArray()),\n elementKeys: instancesByType.element.pipe(toArray()),\n }).pipe(\n mergeMap(({ groupInformationElementKeys, geometricElementKeys, functionalElements, elementKeys }) => {\n const hasFunctionalElements = !!functionalElements.length;\n if (!groupInformationElementKeys.length && !geometricElementKeys.length && !elementKeys.length && !hasFunctionalElements) {\n return EMPTY;\n }\n\n const bindings: ECSqlBinding[] = [];\n const query = `WITH RECURSIVE\n ${hasFunctionalElements ? this.getHilitedFunctionalElementsQuery(functionalElements, bindings) : \"\"}\n GroupMembers (ECInstanceId, ECClassId) AS (\n SELECT TargetECInstanceId, TargetECClassId FROM BisCore.ElementGroupsMembers\n WHERE ${formIdBindings(\"SourceECInstanceId\", groupInformationElementKeys, bindings)}\n ),\n GroupGeometricElements (ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM GroupMembers\n UNION ALL\n SELECT r.ECInstanceId, r.ECClassId FROM GroupGeometricElements s\n JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId\n ),\n ElementGeometricElements (ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM BisCore.Element WHERE ${formIdBindings(\"ECInstanceId\", elementKeys, bindings)}\n UNION ALL\n SELECT r.ECInstanceId, r.ECClassId FROM ElementGeometricElements s\n JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId\n ),\n GeometricElementGeometricElements (ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM BisCore.GeometricElement WHERE ${formIdBindings(\"ECInstanceId\", geometricElementKeys, bindings)}\n UNION ALL\n SELECT r.ECInstanceId, r.ECClassId FROM GeometricElementGeometricElements s\n JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId\n )\n ${\n hasFunctionalElements\n ? `\n SELECT ECInstanceId FROM FunctionalElementChildGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)\n UNION\n `\n : ``\n }\n SELECT ECInstanceId FROM GeometricElementGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)\n UNION\n SELECT ECInstanceId FROM GroupGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)\n UNION\n SELECT ECInstanceId FROM ElementGeometricElements WHERE ECClassId IS (BisCore.GeometricElement);`;\n return from(this._queryExecutor.createQueryReader(query, bindings));\n }),\n map((row) => row.ECInstanceId as string),\n );\n }\n\n private getHilitedFunctionalElementsQuery(functionalElements: string[], bindings: ECSqlBinding[]): string {\n return `ChildFunctionalElements (ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM Functional.FunctionalElement WHERE ${formIdBindings(\"ECInstanceId\", functionalElements, bindings)}\n UNION ALL\n SELECT r.ECInstanceId, r.ECClassId FROM ChildFunctionalElements s\n JOIN Functional.FunctionalElement r ON r.Parent.Id = s.ECInstanceId\n ),\n PhysicalElements (ECInstanceId, ECClassId) AS (\n SELECT r.SourceECInstanceId, r.SourceECClassId FROM ChildFunctionalElements s\n JOIN Functional.PhysicalElementFulfillsFunction r ON r.TargetECInstanceId = s.ECInstanceId\n ),\n DrawingGraphicElements (ECInstanceId, ECClassId) AS (\n SELECT r.SourceECInstanceId, r.SourceECClassId FROM ChildFunctionalElements s\n JOIN Functional.DrawingGraphicRepresentsFunctionalElement r ON r.TargetECInstanceId = s.ECInstanceId\n ),\n PhysicalElementGeometricElements (ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM PhysicalElements\n UNION ALL\n SELECT r.ECInstanceId, r.ECClassId FROM PhysicalElementGeometricElements s\n JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId\n ),\n DrawingGraphicElementGeometricElements (ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM DrawingGraphicElements\n UNION ALL\n SELECT r.ECInstanceId, r.ECClassId FROM DrawingGraphicElementGeometricElements s\n JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId\n ),\n FunctionalElementChildGeometricElements (ECInstanceId, ECClassId) AS (\n SELECT ECInstanceId, ECClassId FROM PhysicalElementGeometricElements\n UNION\n SELECT ECInstanceId, ECClassId FROM DrawingGraphicElementGeometricElements\n ),`;\n }\n\n private async getClass(fullClassName: string): Promise<ECClass | undefined> {\n const { schemaName, className } = parseFullClassName(fullClassName);\n const schema = await this._metadataProvider.getSchema(schemaName);\n if (!schema) {\n return undefined;\n }\n const schemaClass = await schema.getClass(className);\n if (!schemaClass) {\n return undefined;\n }\n return schemaClass;\n }\n}\n\nconst INSTANCE_TYPES = [\n \"subject\",\n \"model\",\n \"category\",\n \"subCategory\",\n \"functionalElement\",\n \"groupInformationElement\",\n \"geometricElement\",\n \"element\",\n \"unknown\",\n] as const;\n\ntype InstanceIdType = (typeof INSTANCE_TYPES)[number];\n\ntype InstancesByType = {\n [idType in InstanceIdType]: Observable<string>;\n};\n\nfunction unique<T>() {\n return function (obs: Observable<T>): Observable<T> {\n return obs.pipe(\n scan(\n (acc, val) => {\n if (acc.set.has(val)) {\n delete acc.val;\n return acc;\n }\n\n acc.set.add(val);\n acc.val = val;\n return acc;\n },\n { set: new Set<T>() } as { set: Set<T>; val?: T },\n ),\n map(({ val }) => val),\n filter((x): x is T => !!x),\n );\n };\n}\n"]}
|