@itwin/unified-selection 0.2.0 → 0.3.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.
Files changed (94) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +34 -14
  3. package/lib/cjs/unified-selection/CachingHiliteSetProvider.d.ts +3 -7
  4. package/lib/cjs/unified-selection/CachingHiliteSetProvider.d.ts.map +1 -1
  5. package/lib/cjs/unified-selection/CachingHiliteSetProvider.js +14 -17
  6. package/lib/cjs/unified-selection/CachingHiliteSetProvider.js.map +1 -1
  7. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts +90 -0
  8. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts.map +1 -0
  9. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.js +205 -0
  10. package/lib/cjs/unified-selection/EnableUnifiedSelectionSyncWithIModel.js.map +1 -0
  11. package/lib/cjs/unified-selection/HiliteSetProvider.d.ts +2 -4
  12. package/lib/cjs/unified-selection/HiliteSetProvider.d.ts.map +1 -1
  13. package/lib/cjs/unified-selection/HiliteSetProvider.js +156 -110
  14. package/lib/cjs/unified-selection/HiliteSetProvider.js.map +1 -1
  15. package/lib/cjs/unified-selection/Selectable.d.ts +0 -3
  16. package/lib/cjs/unified-selection/Selectable.d.ts.map +1 -1
  17. package/lib/cjs/unified-selection/Selectable.js +2 -2
  18. package/lib/cjs/unified-selection/Selectable.js.map +1 -1
  19. package/lib/cjs/unified-selection/SelectionChangeEvent.d.ts +5 -3
  20. package/lib/cjs/unified-selection/SelectionChangeEvent.d.ts.map +1 -1
  21. package/lib/cjs/unified-selection/SelectionChangeEvent.js.map +1 -1
  22. package/lib/cjs/unified-selection/SelectionScope.d.ts +2 -2
  23. package/lib/cjs/unified-selection/SelectionScope.d.ts.map +1 -1
  24. package/lib/cjs/unified-selection/SelectionScope.js +87 -54
  25. package/lib/cjs/unified-selection/SelectionScope.js.map +1 -1
  26. package/lib/cjs/unified-selection/SelectionStorage.d.ts +20 -28
  27. package/lib/cjs/unified-selection/SelectionStorage.d.ts.map +1 -1
  28. package/lib/cjs/unified-selection/SelectionStorage.js +21 -18
  29. package/lib/cjs/unified-selection/SelectionStorage.js.map +1 -1
  30. package/lib/cjs/unified-selection/Utils.d.ts +7 -0
  31. package/lib/cjs/unified-selection/Utils.d.ts.map +1 -0
  32. package/lib/cjs/unified-selection/{queries/ECSqlCore.js → Utils.js} +2 -1
  33. package/lib/cjs/unified-selection/Utils.js.map +1 -0
  34. package/lib/cjs/unified-selection/types/IModel.d.ts +84 -0
  35. package/lib/cjs/unified-selection/types/IModel.d.ts.map +1 -0
  36. package/lib/cjs/unified-selection/types/IModel.js +24 -0
  37. package/lib/cjs/unified-selection/types/IModel.js.map +1 -0
  38. package/lib/cjs/unified-selection.d.ts +1 -6
  39. package/lib/cjs/unified-selection.d.ts.map +1 -1
  40. package/lib/cjs/unified-selection.js +3 -7
  41. package/lib/cjs/unified-selection.js.map +1 -1
  42. package/lib/esm/unified-selection/CachingHiliteSetProvider.d.ts +3 -7
  43. package/lib/esm/unified-selection/CachingHiliteSetProvider.d.ts.map +1 -1
  44. package/lib/esm/unified-selection/CachingHiliteSetProvider.js +14 -17
  45. package/lib/esm/unified-selection/CachingHiliteSetProvider.js.map +1 -1
  46. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts +90 -0
  47. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.d.ts.map +1 -0
  48. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.js +200 -0
  49. package/lib/esm/unified-selection/EnableUnifiedSelectionSyncWithIModel.js.map +1 -0
  50. package/lib/esm/unified-selection/HiliteSetProvider.d.ts +2 -4
  51. package/lib/esm/unified-selection/HiliteSetProvider.d.ts.map +1 -1
  52. package/lib/esm/unified-selection/HiliteSetProvider.js +155 -109
  53. package/lib/esm/unified-selection/HiliteSetProvider.js.map +1 -1
  54. package/lib/esm/unified-selection/Selectable.d.ts +0 -3
  55. package/lib/esm/unified-selection/Selectable.d.ts.map +1 -1
  56. package/lib/esm/unified-selection/Selectable.js.map +1 -1
  57. package/lib/esm/unified-selection/SelectionChangeEvent.d.ts +5 -3
  58. package/lib/esm/unified-selection/SelectionChangeEvent.d.ts.map +1 -1
  59. package/lib/esm/unified-selection/SelectionChangeEvent.js.map +1 -1
  60. package/lib/esm/unified-selection/SelectionScope.d.ts +2 -2
  61. package/lib/esm/unified-selection/SelectionScope.d.ts.map +1 -1
  62. package/lib/esm/unified-selection/SelectionScope.js +84 -51
  63. package/lib/esm/unified-selection/SelectionScope.js.map +1 -1
  64. package/lib/esm/unified-selection/SelectionStorage.d.ts +20 -28
  65. package/lib/esm/unified-selection/SelectionStorage.d.ts.map +1 -1
  66. package/lib/esm/unified-selection/SelectionStorage.js +21 -18
  67. package/lib/esm/unified-selection/SelectionStorage.js.map +1 -1
  68. package/lib/esm/unified-selection/Utils.d.ts +7 -0
  69. package/lib/esm/unified-selection/Utils.d.ts.map +1 -0
  70. package/lib/esm/unified-selection/{queries/ECSqlCore.js → Utils.js} +2 -1
  71. package/lib/esm/unified-selection/Utils.js.map +1 -0
  72. package/lib/esm/unified-selection/types/IModel.d.ts +84 -0
  73. package/lib/esm/unified-selection/types/IModel.d.ts.map +1 -0
  74. package/lib/esm/unified-selection/types/IModel.js +21 -0
  75. package/lib/esm/unified-selection/types/IModel.js.map +1 -0
  76. package/lib/esm/unified-selection.d.ts +1 -6
  77. package/lib/esm/unified-selection.d.ts.map +1 -1
  78. package/lib/esm/unified-selection.js +1 -6
  79. package/lib/esm/unified-selection.js.map +1 -1
  80. package/package.json +23 -16
  81. package/lib/cjs/unified-selection/queries/ECMetadata.d.ts +0 -44
  82. package/lib/cjs/unified-selection/queries/ECMetadata.d.ts.map +0 -1
  83. package/lib/cjs/unified-selection/queries/ECMetadata.js +0 -17
  84. package/lib/cjs/unified-selection/queries/ECMetadata.js.map +0 -1
  85. package/lib/cjs/unified-selection/queries/ECSqlCore.d.ts +0 -69
  86. package/lib/cjs/unified-selection/queries/ECSqlCore.d.ts.map +0 -1
  87. package/lib/cjs/unified-selection/queries/ECSqlCore.js.map +0 -1
  88. package/lib/esm/unified-selection/queries/ECMetadata.d.ts +0 -44
  89. package/lib/esm/unified-selection/queries/ECMetadata.d.ts.map +0 -1
  90. package/lib/esm/unified-selection/queries/ECMetadata.js +0 -13
  91. package/lib/esm/unified-selection/queries/ECMetadata.js.map +0 -1
  92. package/lib/esm/unified-selection/queries/ECSqlCore.d.ts +0 -69
  93. package/lib/esm/unified-selection/queries/ECSqlCore.d.ts.map +0 -1
  94. package/lib/esm/unified-selection/queries/ECSqlCore.js.map +0 -1
@@ -0,0 +1,200 @@
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
+ import { from, Subject, takeUntil } from "rxjs";
6
+ import { assert, using } from "@itwin/core-bentley";
7
+ import { createCachingHiliteSetProvider } from "./CachingHiliteSetProvider";
8
+ import { createHiliteSetProvider } from "./HiliteSetProvider";
9
+ import { computeSelection } from "./SelectionScope";
10
+ import { CoreSelectionSetEventType } from "./types/IModel";
11
+ /**
12
+ * Enables synchronization between iModel selection and unified selection.
13
+ * @returns function for disposing the synchronization.
14
+ * @beta
15
+ */
16
+ export function enableUnifiedSelectionSyncWithIModel(props) {
17
+ const selectionHandler = new IModelSelectionHandler(props);
18
+ return () => selectionHandler.dispose();
19
+ }
20
+ /**
21
+ * A handler that syncs selection between unified selection storage
22
+ * (`SelectionStorage`) and an iModel (`iModel.selectionSet`, `iModel.hilited`).
23
+ * @internal
24
+ */
25
+ export class IModelSelectionHandler {
26
+ _selectionSourceName = "Tool";
27
+ _imodelAccess;
28
+ _selectionStorage;
29
+ _hiliteSetProvider;
30
+ _cachingHiliteSetProvider;
31
+ _activeScopeProvider;
32
+ _isSuspended;
33
+ _cancelOngoingChanges = new Subject();
34
+ _unifiedSelectionListenerDisposeFunc;
35
+ _imodelListenerDisposeFunc;
36
+ _hasCustomCachingHiliteSetProvider;
37
+ constructor(props) {
38
+ this._imodelAccess = props.imodelAccess;
39
+ this._selectionStorage = props.selectionStorage;
40
+ this._activeScopeProvider = props.activeScopeProvider;
41
+ this._isSuspended = false;
42
+ this._hasCustomCachingHiliteSetProvider = !!props.cachingHiliteSetProvider;
43
+ this._cachingHiliteSetProvider =
44
+ props.cachingHiliteSetProvider ??
45
+ createCachingHiliteSetProvider({
46
+ selectionStorage: this._selectionStorage,
47
+ imodelProvider: () => this._imodelAccess,
48
+ });
49
+ this._hiliteSetProvider = createHiliteSetProvider({ imodelAccess: this._imodelAccess });
50
+ this._imodelListenerDisposeFunc = this._imodelAccess.selectionSet.onChanged.addListener(this.onIModelSelectionChanged);
51
+ this._unifiedSelectionListenerDisposeFunc = this._selectionStorage.selectionChangeEvent.addListener(this.onUnifiedSelectionChanged);
52
+ // stop imodel from syncing tool selection with hilited list - we want to override that behavior
53
+ this._imodelAccess.hiliteSet.wantSyncWithSelectionSet = false;
54
+ this.applyCurrentHiliteSet({ activeSelectionAction: "clearAll" });
55
+ }
56
+ dispose() {
57
+ this._cancelOngoingChanges.next();
58
+ this._imodelListenerDisposeFunc();
59
+ this._unifiedSelectionListenerDisposeFunc();
60
+ if (!this._hasCustomCachingHiliteSetProvider) {
61
+ this._cachingHiliteSetProvider.dispose();
62
+ }
63
+ }
64
+ /** Temporarily suspends tool selection synchronization until the returned `IDisposable` is disposed. */
65
+ suspendIModelToolSelectionSync() {
66
+ const wasSuspended = this._isSuspended;
67
+ this._isSuspended = true;
68
+ return {
69
+ dispose: () => (this._isSuspended = wasSuspended),
70
+ };
71
+ }
72
+ handleUnifiedSelectionChange(changeType, selectables, source) {
73
+ if (changeType === "clear" || changeType === "replace") {
74
+ this.applyCurrentHiliteSet({ activeSelectionAction: changeType === "replace" && source === "Tool" ? "clearHilited" : "clearAll" });
75
+ return;
76
+ }
77
+ if (changeType === "add") {
78
+ from(this._hiliteSetProvider.getHiliteSet({ selectables }))
79
+ .pipe(takeUntil(this._cancelOngoingChanges))
80
+ .subscribe({
81
+ next: (set) => {
82
+ this.addHiliteSet(set);
83
+ },
84
+ });
85
+ return;
86
+ }
87
+ from(this._hiliteSetProvider.getHiliteSet({ selectables }))
88
+ .pipe(takeUntil(this._cancelOngoingChanges))
89
+ .subscribe({
90
+ next: (set) => {
91
+ this.removeHiliteSet(set);
92
+ },
93
+ complete: () => {
94
+ this.applyCurrentHiliteSet({ activeSelectionAction: "keep" });
95
+ },
96
+ });
97
+ }
98
+ onUnifiedSelectionChanged = (args) => {
99
+ // iModels are only interested in top-level selection changes
100
+ if (args.imodelKey !== this._imodelAccess.key || args.level !== 0) {
101
+ return;
102
+ }
103
+ if (args.changeType === "replace" || args.changeType === "clear") {
104
+ this._cancelOngoingChanges.next();
105
+ }
106
+ this.handleUnifiedSelectionChange(args.changeType, args.selectables, args.source);
107
+ };
108
+ applyCurrentHiliteSet({ activeSelectionAction }) {
109
+ if (activeSelectionAction !== "keep") {
110
+ using(this.suspendIModelToolSelectionSync(), (_) => {
111
+ this._imodelAccess.hiliteSet.clear();
112
+ if (activeSelectionAction === "clearAll") {
113
+ this._imodelAccess.selectionSet.emptyAll();
114
+ }
115
+ });
116
+ }
117
+ from(this._cachingHiliteSetProvider.getHiliteSet({ imodelKey: this._imodelAccess.key }))
118
+ .pipe(takeUntil(this._cancelOngoingChanges))
119
+ .subscribe({
120
+ next: (ids) => {
121
+ this.addHiliteSet(ids);
122
+ },
123
+ });
124
+ }
125
+ addHiliteSet(set) {
126
+ using(this.suspendIModelToolSelectionSync(), (_) => {
127
+ if (set.models && set.models.length) {
128
+ this._imodelAccess.hiliteSet.models.addIds(set.models);
129
+ }
130
+ if (set.subCategories && set.subCategories.length) {
131
+ this._imodelAccess.hiliteSet.subcategories.addIds(set.subCategories);
132
+ }
133
+ if (set.elements && set.elements.length) {
134
+ this._imodelAccess.hiliteSet.elements.addIds(set.elements);
135
+ this._imodelAccess.selectionSet.add(set.elements);
136
+ }
137
+ });
138
+ }
139
+ removeHiliteSet(set) {
140
+ using(this.suspendIModelToolSelectionSync(), (_) => {
141
+ if (set.models.length) {
142
+ this._imodelAccess.hiliteSet.models.deleteIds(set.models);
143
+ }
144
+ if (set.subCategories.length) {
145
+ this._imodelAccess.hiliteSet.subcategories.deleteIds(set.subCategories);
146
+ }
147
+ if (set.elements.length) {
148
+ this._imodelAccess.hiliteSet.elements.deleteIds(set.elements);
149
+ this._imodelAccess.selectionSet.remove(set.elements);
150
+ }
151
+ });
152
+ }
153
+ onIModelSelectionChanged = async (event) => {
154
+ if (this._isSuspended) {
155
+ return;
156
+ }
157
+ if (CoreSelectionSetEventType.Clear === event.type) {
158
+ this._selectionStorage.clearSelection({ imodelKey: this._imodelAccess.key, source: this._selectionSourceName });
159
+ return;
160
+ }
161
+ const elementIds = this.getSelectionSetChangeIds(event);
162
+ const scopedSelection = computeSelection({ queryExecutor: this._imodelAccess, elementIds, scope: this._activeScopeProvider() });
163
+ await this.handleIModelSelectionChange(event.type, scopedSelection);
164
+ };
165
+ async handleIModelSelectionChange(type, iterator) {
166
+ if (type === CoreSelectionSetEventType.Remove) {
167
+ for await (const selectable of iterator) {
168
+ this._selectionStorage.removeFromSelection({ imodelKey: this._imodelAccess.key, source: this._selectionSourceName, selectables: [selectable] });
169
+ }
170
+ return;
171
+ }
172
+ if (type === CoreSelectionSetEventType.Replace) {
173
+ this._selectionStorage.clearSelection({ imodelKey: this._imodelAccess.key, source: this._selectionSourceName });
174
+ }
175
+ for await (const selectable of iterator) {
176
+ this._selectionStorage.addToSelection({ imodelKey: this._imodelAccess.key, source: this._selectionSourceName, selectables: [selectable] });
177
+ }
178
+ }
179
+ getSelectionSetChangeIds(event) {
180
+ switch (event.type) {
181
+ case CoreSelectionSetEventType.Add:
182
+ case CoreSelectionSetEventType.Replace:
183
+ assert(!!event.added);
184
+ return this.idArgToIds(event.added);
185
+ default:
186
+ assert(!!event.removed);
187
+ return this.idArgToIds(event.removed);
188
+ }
189
+ }
190
+ idArgToIds(ids) {
191
+ if (typeof ids === "string") {
192
+ return [ids];
193
+ }
194
+ if (ids instanceof Set) {
195
+ return [...ids];
196
+ }
197
+ return ids;
198
+ }
199
+ }
200
+ //# sourceMappingURL=EnableUnifiedSelectionSyncWithIModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnableUnifiedSelectionSyncWithIModel.js","sourceRoot":"","sources":["../../../src/unified-selection/EnableUnifiedSelectionSyncWithIModel.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\nimport { from, Subject, takeUntil } from \"rxjs\";\nimport { assert, Id64Arg, using } from \"@itwin/core-bentley\";\nimport { ECSchemaProvider, ECSqlQueryExecutor } from \"@itwin/presentation-shared\";\nimport { CachingHiliteSetProvider, createCachingHiliteSetProvider } from \"./CachingHiliteSetProvider\";\nimport { createHiliteSetProvider, HiliteSet, HiliteSetProvider } from \"./HiliteSetProvider\";\nimport { SelectableInstanceKey, Selectables } from \"./Selectable\";\nimport { StorageSelectionChangeEventArgs, StorageSelectionChangeType } from \"./SelectionChangeEvent\";\nimport { computeSelection, ComputeSelectionProps } from \"./SelectionScope\";\nimport { SelectionStorage } from \"./SelectionStorage\";\nimport { CoreIModelHiliteSet, CoreIModelSelectionSet, CoreSelectionSetEventType, CoreSelectionSetEventUnsafe } from \"./types/IModel\";\n\n/**\n * Props for `enableUnifiedSelectionSyncWithIModel`.\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 EnableUnifiedSelectionSyncWithIModelProps {\n /**\n * Provides access to different iModel's features: query executing, metadata access, selection and hilite sets.\n * It's recommended to use `@itwin/presentation-core-interop` to create `ECSqlQueryExecutor` and `ECSchemaProvider` from\n * [IModelConnection](https://www.itwinjs.org/reference/core-frontend/imodelconnection/imodelconnection/) and map its `key`,\n * `hilited` and `selectionSet` attributes like this:\n *\n * ```ts\n * import { createECSqlQueryExecutor, createECSchemaProvider } from \"@itwin/presentation-core-interop\";\n * import { IModelConnection } from \"@itwin/core-frontend\";\n *\n * const imodel: IModelConnection = ...\n * const imodelAccess = {\n * ...createECSqlQueryExecutor(imodel),\n * ...createECSchemaProvider(MyAppFrontend.getSchemaContext(imodel)),\n * key: imodel.key,\n * hiliteSet: imodel.hilited,\n * selectionSet: imodel.selectionSet,\n * };\n * ```.\n */\n imodelAccess: ECSqlQueryExecutor &\n ECSchemaProvider & {\n /** Key of the iModel. Generally taken from `IModelConnection.key`. */\n readonly key: string;\n /** The set of currently hilited elements taken from `IModelConnection.hilited`. */\n readonly hiliteSet: CoreIModelHiliteSet;\n /** The set of currently selected elements taken from `IModelConnection.selectionSet`. */\n readonly selectionSet: CoreIModelSelectionSet;\n };\n\n /** Selection storage to synchronize IModel's tool selection with. */\n selectionStorage: SelectionStorage;\n\n /** Active scope provider. */\n activeScopeProvider: () => ComputeSelectionProps[\"scope\"];\n\n /**\n * A caching hilite set provider used to retrieve hilite sets for an iModel. If not provided, a new `CachingHiliteSetProvider`\n * will be created for the given iModel using the provided `imodelAccess`.\n * If the consuming application already has a `CachingHiliteSetProvider` defined, it should be provided instead\n * to reuse the cache and avoid creating new providers for each iModel.\n */\n cachingHiliteSetProvider?: CachingHiliteSetProvider;\n}\n\n/**\n * Enables synchronization between iModel selection and unified selection.\n * @returns function for disposing the synchronization.\n * @beta\n */\nexport function enableUnifiedSelectionSyncWithIModel(props: EnableUnifiedSelectionSyncWithIModelProps): () => void {\n const selectionHandler = new IModelSelectionHandler(props);\n return () => selectionHandler.dispose();\n}\n\n/**\n * A handler that syncs selection between unified selection storage\n * (`SelectionStorage`) and an iModel (`iModel.selectionSet`, `iModel.hilited`).\n * @internal\n */\nexport class IModelSelectionHandler {\n private _selectionSourceName = \"Tool\";\n\n private _imodelAccess: EnableUnifiedSelectionSyncWithIModelProps[\"imodelAccess\"];\n private _selectionStorage: SelectionStorage;\n private _hiliteSetProvider: HiliteSetProvider;\n private _cachingHiliteSetProvider: CachingHiliteSetProvider;\n private _activeScopeProvider: () => ComputeSelectionProps[\"scope\"];\n\n private _isSuspended: boolean;\n private _cancelOngoingChanges = new Subject<void>();\n private _unifiedSelectionListenerDisposeFunc: () => void;\n private _imodelListenerDisposeFunc: () => void;\n private _hasCustomCachingHiliteSetProvider: boolean;\n\n public constructor(props: EnableUnifiedSelectionSyncWithIModelProps) {\n this._imodelAccess = props.imodelAccess;\n this._selectionStorage = props.selectionStorage;\n this._activeScopeProvider = props.activeScopeProvider;\n this._isSuspended = false;\n this._hasCustomCachingHiliteSetProvider = !!props.cachingHiliteSetProvider;\n\n this._cachingHiliteSetProvider =\n props.cachingHiliteSetProvider ??\n createCachingHiliteSetProvider({\n selectionStorage: this._selectionStorage,\n imodelProvider: () => this._imodelAccess,\n });\n\n this._hiliteSetProvider = createHiliteSetProvider({ imodelAccess: this._imodelAccess });\n this._imodelListenerDisposeFunc = this._imodelAccess.selectionSet.onChanged.addListener(this.onIModelSelectionChanged);\n this._unifiedSelectionListenerDisposeFunc = this._selectionStorage.selectionChangeEvent.addListener(this.onUnifiedSelectionChanged);\n\n // stop imodel from syncing tool selection with hilited list - we want to override that behavior\n this._imodelAccess.hiliteSet.wantSyncWithSelectionSet = false;\n this.applyCurrentHiliteSet({ activeSelectionAction: \"clearAll\" });\n }\n\n public dispose() {\n this._cancelOngoingChanges.next();\n this._imodelListenerDisposeFunc();\n this._unifiedSelectionListenerDisposeFunc();\n if (!this._hasCustomCachingHiliteSetProvider) {\n this._cachingHiliteSetProvider.dispose();\n }\n }\n\n /** Temporarily suspends tool selection synchronization until the returned `IDisposable` is disposed. */\n public suspendIModelToolSelectionSync() {\n const wasSuspended = this._isSuspended;\n this._isSuspended = true;\n return {\n dispose: () => (this._isSuspended = wasSuspended),\n };\n }\n\n private handleUnifiedSelectionChange(changeType: StorageSelectionChangeType, selectables: Selectables, source: string) {\n if (changeType === \"clear\" || changeType === \"replace\") {\n this.applyCurrentHiliteSet({ activeSelectionAction: changeType === \"replace\" && source === \"Tool\" ? \"clearHilited\" : \"clearAll\" });\n return;\n }\n\n if (changeType === \"add\") {\n from(this._hiliteSetProvider.getHiliteSet({ selectables }))\n .pipe(takeUntil(this._cancelOngoingChanges))\n .subscribe({\n next: (set) => {\n this.addHiliteSet(set);\n },\n });\n return;\n }\n\n from(this._hiliteSetProvider.getHiliteSet({ selectables }))\n .pipe(takeUntil(this._cancelOngoingChanges))\n .subscribe({\n next: (set) => {\n this.removeHiliteSet(set);\n },\n complete: () => {\n this.applyCurrentHiliteSet({ activeSelectionAction: \"keep\" });\n },\n });\n }\n\n private onUnifiedSelectionChanged = (args: StorageSelectionChangeEventArgs) => {\n // iModels are only interested in top-level selection changes\n if (args.imodelKey !== this._imodelAccess.key || args.level !== 0) {\n return;\n }\n\n if (args.changeType === \"replace\" || args.changeType === \"clear\") {\n this._cancelOngoingChanges.next();\n }\n this.handleUnifiedSelectionChange(args.changeType, args.selectables, args.source);\n };\n\n private applyCurrentHiliteSet({ activeSelectionAction }: { activeSelectionAction: \"clearAll\" | \"clearHilited\" | \"keep\" }) {\n if (activeSelectionAction !== \"keep\") {\n using(this.suspendIModelToolSelectionSync(), (_) => {\n this._imodelAccess.hiliteSet.clear();\n if (activeSelectionAction === \"clearAll\") {\n this._imodelAccess.selectionSet.emptyAll();\n }\n });\n }\n\n from(this._cachingHiliteSetProvider.getHiliteSet({ imodelKey: this._imodelAccess.key }))\n .pipe(takeUntil(this._cancelOngoingChanges))\n .subscribe({\n next: (ids) => {\n this.addHiliteSet(ids);\n },\n });\n }\n\n private addHiliteSet(set: HiliteSet) {\n using(this.suspendIModelToolSelectionSync(), (_) => {\n if (set.models && set.models.length) {\n this._imodelAccess.hiliteSet.models.addIds(set.models);\n }\n if (set.subCategories && set.subCategories.length) {\n this._imodelAccess.hiliteSet.subcategories.addIds(set.subCategories);\n }\n if (set.elements && set.elements.length) {\n this._imodelAccess.hiliteSet.elements.addIds(set.elements);\n this._imodelAccess.selectionSet.add(set.elements);\n }\n });\n }\n\n private removeHiliteSet(set: HiliteSet) {\n using(this.suspendIModelToolSelectionSync(), (_) => {\n if (set.models.length) {\n this._imodelAccess.hiliteSet.models.deleteIds(set.models);\n }\n if (set.subCategories.length) {\n this._imodelAccess.hiliteSet.subcategories.deleteIds(set.subCategories);\n }\n if (set.elements.length) {\n this._imodelAccess.hiliteSet.elements.deleteIds(set.elements);\n this._imodelAccess.selectionSet.remove(set.elements);\n }\n });\n }\n\n private onIModelSelectionChanged = async (event?: CoreSelectionSetEventUnsafe): Promise<void> => {\n if (this._isSuspended) {\n return;\n }\n\n if (CoreSelectionSetEventType.Clear === event!.type) {\n this._selectionStorage.clearSelection({ imodelKey: this._imodelAccess.key, source: this._selectionSourceName });\n return;\n }\n\n const elementIds = this.getSelectionSetChangeIds(event!);\n const scopedSelection = computeSelection({ queryExecutor: this._imodelAccess, elementIds, scope: this._activeScopeProvider() });\n await this.handleIModelSelectionChange(event!.type, scopedSelection);\n };\n\n private async handleIModelSelectionChange(type: CoreSelectionSetEventType, iterator: AsyncIterableIterator<SelectableInstanceKey>) {\n if (type === CoreSelectionSetEventType.Remove) {\n for await (const selectable of iterator) {\n this._selectionStorage.removeFromSelection({ imodelKey: this._imodelAccess.key, source: this._selectionSourceName, selectables: [selectable] });\n }\n return;\n }\n\n if (type === CoreSelectionSetEventType.Replace) {\n this._selectionStorage.clearSelection({ imodelKey: this._imodelAccess.key, source: this._selectionSourceName });\n }\n\n for await (const selectable of iterator) {\n this._selectionStorage.addToSelection({ imodelKey: this._imodelAccess.key, source: this._selectionSourceName, selectables: [selectable] });\n }\n }\n\n private getSelectionSetChangeIds(event: CoreSelectionSetEventUnsafe): string[] {\n switch (event.type) {\n case CoreSelectionSetEventType.Add:\n case CoreSelectionSetEventType.Replace:\n assert(!!event.added);\n return this.idArgToIds(event.added);\n default:\n assert(!!event.removed);\n return this.idArgToIds(event.removed);\n }\n }\n\n private idArgToIds(ids: Id64Arg): string[] {\n if (typeof ids === \"string\") {\n return [ids];\n }\n if (ids instanceof Set) {\n return [...ids];\n }\n return ids;\n }\n}\n"]}
@@ -1,5 +1,4 @@
1
- import { IMetadataProvider } from "./queries/ECMetadata";
2
- import { IECSqlQueryExecutor } from "./queries/ECSqlCore";
1
+ import { ECSchemaProvider, ECSqlQueryExecutor } from "@itwin/presentation-shared";
3
2
  import { Selectables } from "./Selectable";
4
3
  /**
5
4
  * A set of model, subcategory and element ids that can be used for specifying hilite.
@@ -16,8 +15,7 @@ export interface HiliteSet {
16
15
  * @internal Not exported through barrel, but used in public API as an argument. May be supplemented with optional attributes any time.
17
16
  */
18
17
  export interface HiliteSetProviderProps {
19
- queryExecutor: IECSqlQueryExecutor;
20
- metadataProvider: IMetadataProvider;
18
+ imodelAccess: ECSchemaProvider & ECSqlQueryExecutor;
21
19
  }
22
20
  /**
23
21
  * Defines return value of `createHiliteSetProvider`.
@@ -1 +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"}
1
+ {"version":3,"file":"HiliteSetProvider.d.ts","sourceRoot":"","sources":["../../../src/unified-selection/HiliteSetProvider.ts"],"names":[],"mappings":"AAOA,OAAO,EAAM,gBAAgB,EAAgB,kBAAkB,EAAsB,MAAM,4BAA4B,CAAC;AACxH,OAAO,EAAyB,WAAW,EAAE,MAAM,cAAc,CAAC;AAKlE;;;;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,YAAY,EAAE,gBAAgB,GAAG,kBAAkB,CAAC;CACrD;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"}
@@ -2,13 +2,10 @@
2
2
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
- /** @packageDocumentation
6
- * @module UnifiedSelection
7
- */
8
5
  import { EMPTY, filter, forkJoin, from, map, merge, mergeMap, scan, shareReplay, Subject, toArray } from "rxjs";
9
6
  import { eachValueFrom } from "rxjs-for-await";
10
- import { parseFullClassName } from "./queries/ECMetadata";
11
- import { formIdBindings } from "./queries/ECSqlCore";
7
+ import { parseFullClassName } from "@itwin/presentation-shared";
8
+ import { formIdBindings } from "./Utils";
12
9
  const HILITE_SET_EMIT_FREQUENCY = 20;
13
10
  /**
14
11
  * Creates a hilite set provider that returns a `HiliteSet` for given selectables.
@@ -18,13 +15,11 @@ export function createHiliteSetProvider(props) {
18
15
  return new HiliteSetProviderImpl(props);
19
16
  }
20
17
  class HiliteSetProviderImpl {
21
- _queryExecutor;
22
- _metadataProvider;
18
+ _imodelAccess;
23
19
  // Map between a class name and its type
24
20
  _classRelationCache;
25
21
  constructor(props) {
26
- this._queryExecutor = props.queryExecutor;
27
- this._metadataProvider = props.metadataProvider;
22
+ this._imodelAccess = props.imodelAccess;
28
23
  this._classRelationCache = new Map();
29
24
  }
30
25
  /**
@@ -126,24 +121,37 @@ class HiliteSetProviderImpl {
126
121
  return EMPTY;
127
122
  }
128
123
  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));
124
+ const ctes = [
125
+ `
126
+ ChildSubjects(ECInstanceId, JsonProperties) AS (
127
+ SELECT ECInstanceId, JsonProperties
128
+ FROM BisCore.Subject
129
+ WHERE ${formIdBindings("ECInstanceId", subjectKeys, bindings)}
130
+ UNION ALL
131
+ SELECT r.ECInstanceId, r.JsonProperties
132
+ FROM ChildSubjects s
133
+ JOIN BisCore.Subject r ON r.Parent.Id = s.ECInstanceId
134
+ )
135
+ `,
136
+ `
137
+ Models(ECInstanceId) AS (
138
+ SELECT s.ECInstanceId AS ECInstanceId
139
+ FROM BisCore.Model s
140
+ WHERE ${formIdBindings("ECInstanceId", modelKeys, bindings)}
141
+ )
142
+ `,
143
+ ];
144
+ const ecsql = [
145
+ `
146
+ SELECT r.ECInstanceId AS ECInstanceId
147
+ FROM ChildSubjects s
148
+ JOIN BisCore.PhysicalPartition r ON r.Parent.Id = s.ECInstanceId OR json_extract(s.JsonProperties,'$.Subject.Model.TargetPartition') = printf('0x%x', r.ECInstanceId)
149
+ `,
150
+ `
151
+ SELECT ECInstanceId FROM Models
152
+ `,
153
+ ].join(" UNION ");
154
+ return from(this._imodelAccess.createQueryReader({ ctes, ecsql, bindings }));
147
155
  }), map((row) => row.ECInstanceId));
148
156
  }
149
157
  getHilitedSubCategories(instancesByType) {
@@ -155,20 +163,25 @@ class HiliteSetProviderImpl {
155
163
  return EMPTY;
156
164
  }
157
165
  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));
166
+ const ctes = [
167
+ `
168
+ CategorySubCategories(ECInstanceId) AS (
169
+ SELECT r.ECInstanceId AS ECInstanceId
170
+ FROM BisCore.Category s
171
+ JOIN BisCore.SubCategory r ON r.Parent.Id = s.ECInstanceId
172
+ WHERE ${formIdBindings("s.ECInstanceId", categoryKeys, bindings)}
173
+ )
174
+ `,
175
+ `
176
+ SubCategories(ECInstanceId) AS (
177
+ SELECT s.ECInstanceId AS ECInstanceId
178
+ FROM BisCore.SubCategory s
179
+ WHERE ${formIdBindings("s.ECInstanceId", subCategoryKeys, bindings)}
180
+ )
181
+ `,
182
+ ];
183
+ const ecsql = [`SELECT ECInstanceId FROM CategorySubCategories`, `SELECT ECInstanceId FROM SubCategories`].join(" UNION ");
184
+ return from(this._imodelAccess.createQueryReader({ ctes, ecsql, bindings }));
172
185
  }), map((row) => row.ECInstanceId));
173
186
  }
174
187
  getHilitedElements(instancesByType) {
@@ -183,80 +196,113 @@ class HiliteSetProviderImpl {
183
196
  return EMPTY;
184
197
  }
185
198
  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)}
199
+ const ctes = [
200
+ ...(hasFunctionalElements ? this.getHilitedFunctionalElementsQueryCTEs(functionalElements, bindings) : []),
201
+ `
202
+ GroupMembers(ECInstanceId, ECClassId) AS (
203
+ SELECT TargetECInstanceId, TargetECClassId
204
+ FROM BisCore.ElementGroupsMembers
205
+ WHERE ${formIdBindings("SourceECInstanceId", groupInformationElementKeys, bindings)}
206
+ )
207
+ `,
208
+ `
209
+ GroupGeometricElements(ECInstanceId, ECClassId) AS (
210
+ SELECT ECInstanceId, ECClassId FROM GroupMembers
227
211
  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
212
+ SELECT r.ECInstanceId, r.ECClassId
213
+ FROM GroupGeometricElements s
214
+ JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
215
+ )
216
+ `,
217
+ `
218
+ ElementGeometricElements(ECInstanceId, ECClassId) AS (
219
+ SELECT ECInstanceId, ECClassId
220
+ FROM BisCore.Element
221
+ WHERE ${formIdBindings("ECInstanceId", elementKeys, bindings)}
241
222
  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
223
+ SELECT r.ECInstanceId, r.ECClassId
224
+ FROM ElementGeometricElements s
225
+ JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
226
+ )
227
+ `,
228
+ `
229
+ GeometricElementGeometricElements(ECInstanceId, ECClassId) AS (
230
+ SELECT ECInstanceId, ECClassId
231
+ FROM BisCore.GeometricElement
232
+ WHERE ${formIdBindings("ECInstanceId", geometricElementKeys, bindings)}
247
233
  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
- ),`;
234
+ SELECT r.ECInstanceId, r.ECClassId
235
+ FROM GeometricElementGeometricElements s
236
+ JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
237
+ )
238
+ `,
239
+ ];
240
+ const ecsql = [
241
+ ...(hasFunctionalElements ? ["SELECT ECInstanceId FROM FunctionalElementChildGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)"] : []),
242
+ "SELECT ECInstanceId FROM GeometricElementGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)",
243
+ "SELECT ECInstanceId FROM GroupGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)",
244
+ "SELECT ECInstanceId FROM ElementGeometricElements WHERE ECClassId IS (BisCore.GeometricElement)",
245
+ ].join(" UNION ");
246
+ return from(this._imodelAccess.createQueryReader({ ctes, ecsql, bindings }));
247
+ }), map((row) => row.ECInstanceId));
248
+ }
249
+ getHilitedFunctionalElementsQueryCTEs(functionalElements, bindings) {
250
+ return [
251
+ `
252
+ ChildFunctionalElements(ECInstanceId, ECClassId) AS (
253
+ SELECT ECInstanceId, ECClassId
254
+ FROM Functional.FunctionalElement
255
+ WHERE ${formIdBindings("ECInstanceId", functionalElements, bindings)}
256
+ UNION ALL
257
+ SELECT r.ECInstanceId, r.ECClassId
258
+ FROM ChildFunctionalElements s
259
+ JOIN Functional.FunctionalElement r ON r.Parent.Id = s.ECInstanceId
260
+ )
261
+ `,
262
+ `
263
+ PhysicalElements(ECInstanceId, ECClassId) AS (
264
+ SELECT r.SourceECInstanceId, r.SourceECClassId
265
+ FROM ChildFunctionalElements s
266
+ JOIN Functional.PhysicalElementFulfillsFunction r ON r.TargetECInstanceId = s.ECInstanceId
267
+ )
268
+ `,
269
+ `
270
+ DrawingGraphicElements(ECInstanceId, ECClassId) AS (
271
+ SELECT r.SourceECInstanceId, r.SourceECClassId
272
+ FROM ChildFunctionalElements s
273
+ JOIN Functional.DrawingGraphicRepresentsFunctionalElement r ON r.TargetECInstanceId = s.ECInstanceId
274
+ )
275
+ `,
276
+ `
277
+ PhysicalElementGeometricElements(ECInstanceId, ECClassId) AS (
278
+ SELECT ECInstanceId, ECClassId FROM PhysicalElements
279
+ UNION ALL
280
+ SELECT r.ECInstanceId, r.ECClassId
281
+ FROM PhysicalElementGeometricElements s
282
+ JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
283
+ )
284
+ `,
285
+ `
286
+ DrawingGraphicElementGeometricElements(ECInstanceId, ECClassId) AS (
287
+ SELECT ECInstanceId, ECClassId FROM DrawingGraphicElements
288
+ UNION ALL
289
+ SELECT r.ECInstanceId, r.ECClassId
290
+ FROM DrawingGraphicElementGeometricElements s
291
+ JOIN BisCore.Element r ON r.Parent.Id = s.ECInstanceId
292
+ )
293
+ `,
294
+ `
295
+ FunctionalElementChildGeometricElements(ECInstanceId, ECClassId) AS (
296
+ SELECT ECInstanceId, ECClassId FROM PhysicalElementGeometricElements
297
+ UNION
298
+ SELECT ECInstanceId, ECClassId FROM DrawingGraphicElementGeometricElements
299
+ )
300
+ `,
301
+ ];
256
302
  }
257
303
  async getClass(fullClassName) {
258
304
  const { schemaName, className } = parseFullClassName(fullClassName);
259
- const schema = await this._metadataProvider.getSchema(schemaName);
305
+ const schema = await this._imodelAccess.getSchema(schemaName);
260
306
  if (!schema) {
261
307
  return undefined;
262
308
  }