@itwin/presentation-hierarchies 1.2.1 → 1.4.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 (71) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +4 -3
  3. package/lib/cjs/hierarchies/HierarchyFiltering.d.ts +48 -3
  4. package/lib/cjs/hierarchies/HierarchyFiltering.d.ts.map +1 -1
  5. package/lib/cjs/hierarchies/HierarchyFiltering.js +137 -2
  6. package/lib/cjs/hierarchies/HierarchyFiltering.js.map +1 -1
  7. package/lib/cjs/hierarchies/HierarchyNode.d.ts +1 -0
  8. package/lib/cjs/hierarchies/HierarchyNode.d.ts.map +1 -1
  9. package/lib/cjs/hierarchies/HierarchyNode.js +3 -0
  10. package/lib/cjs/hierarchies/HierarchyNode.js.map +1 -1
  11. package/lib/cjs/hierarchies/HierarchyProvider.d.ts +45 -8
  12. package/lib/cjs/hierarchies/HierarchyProvider.d.ts.map +1 -1
  13. package/lib/cjs/hierarchies/HierarchyProvider.js +7 -6
  14. package/lib/cjs/hierarchies/HierarchyProvider.js.map +1 -1
  15. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.d.ts +3 -6
  16. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +1 -1
  17. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.js +134 -181
  18. package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.js.map +1 -1
  19. package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts +2 -0
  20. package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
  21. package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js +16 -8
  22. package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
  23. package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.d.ts.map +1 -1
  24. package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.js.map +1 -1
  25. package/lib/cjs/hierarchies/imodel/PredicateBasedHierarchyDefinition.d.ts +1 -1
  26. package/lib/cjs/hierarchies/imodel/PredicateBasedHierarchyDefinition.d.ts.map +1 -1
  27. package/lib/cjs/hierarchies/imodel/PredicateBasedHierarchyDefinition.js +12 -0
  28. package/lib/cjs/hierarchies/imodel/PredicateBasedHierarchyDefinition.js.map +1 -1
  29. package/lib/cjs/hierarchies/internal/Common.d.ts +14 -0
  30. package/lib/cjs/hierarchies/internal/Common.d.ts.map +1 -1
  31. package/lib/cjs/hierarchies/internal/Common.js +18 -0
  32. package/lib/cjs/hierarchies/internal/Common.js.map +1 -1
  33. package/lib/cjs/presentation-hierarchies.d.ts +1 -1
  34. package/lib/cjs/presentation-hierarchies.d.ts.map +1 -1
  35. package/lib/cjs/presentation-hierarchies.js +3 -2
  36. package/lib/cjs/presentation-hierarchies.js.map +1 -1
  37. package/lib/esm/hierarchies/HierarchyFiltering.d.ts +48 -3
  38. package/lib/esm/hierarchies/HierarchyFiltering.d.ts.map +1 -1
  39. package/lib/esm/hierarchies/HierarchyFiltering.js +136 -2
  40. package/lib/esm/hierarchies/HierarchyFiltering.js.map +1 -1
  41. package/lib/esm/hierarchies/HierarchyNode.d.ts +1 -0
  42. package/lib/esm/hierarchies/HierarchyNode.d.ts.map +1 -1
  43. package/lib/esm/hierarchies/HierarchyNode.js +3 -0
  44. package/lib/esm/hierarchies/HierarchyNode.js.map +1 -1
  45. package/lib/esm/hierarchies/HierarchyProvider.d.ts +45 -8
  46. package/lib/esm/hierarchies/HierarchyProvider.d.ts.map +1 -1
  47. package/lib/esm/hierarchies/HierarchyProvider.js +8 -7
  48. package/lib/esm/hierarchies/HierarchyProvider.js.map +1 -1
  49. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.d.ts +3 -6
  50. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +1 -1
  51. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.js +132 -180
  52. package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.js.map +1 -1
  53. package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts +2 -0
  54. package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
  55. package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js +16 -8
  56. package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
  57. package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.d.ts.map +1 -1
  58. package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.js.map +1 -1
  59. package/lib/esm/hierarchies/imodel/PredicateBasedHierarchyDefinition.d.ts +1 -1
  60. package/lib/esm/hierarchies/imodel/PredicateBasedHierarchyDefinition.d.ts.map +1 -1
  61. package/lib/esm/hierarchies/imodel/PredicateBasedHierarchyDefinition.js +12 -0
  62. package/lib/esm/hierarchies/imodel/PredicateBasedHierarchyDefinition.js.map +1 -1
  63. package/lib/esm/hierarchies/internal/Common.d.ts +14 -0
  64. package/lib/esm/hierarchies/internal/Common.d.ts.map +1 -1
  65. package/lib/esm/hierarchies/internal/Common.js +17 -0
  66. package/lib/esm/hierarchies/internal/Common.js.map +1 -1
  67. package/lib/esm/presentation-hierarchies.d.ts +1 -1
  68. package/lib/esm/presentation-hierarchies.d.ts.map +1 -1
  69. package/lib/esm/presentation-hierarchies.js +1 -1
  70. package/lib/esm/presentation-hierarchies.js.map +1 -1
  71. package/package.json +6 -6
@@ -2,11 +2,13 @@
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
- import { extractFilteringProps, HierarchyFilteringPath } from "../HierarchyFiltering.js";
6
- import { HierarchyNodeFilteringProps } from "../HierarchyNode.js";
5
+ import { defer, filter, firstValueFrom, map, merge, mergeMap, of, toArray } from "rxjs";
6
+ import { createHierarchyFilteringHelper } from "../HierarchyFiltering.js";
7
7
  import { HierarchyNodeIdentifier } from "../HierarchyNodeIdentifier.js";
8
+ import { partition } from "../internal/operators/Partition.js";
8
9
  import { HierarchyNodesDefinition, } from "./IModelHierarchyDefinition.js";
9
10
  import { ProcessedHierarchyNode } from "./IModelHierarchyNode.js";
11
+ import { NodeSelectClauseColumnNames } from "./NodeSelectQueryFactory.js";
10
12
  import { defaultNodesParser } from "./TreeNodesReader.js";
11
13
  /** @internal */
12
14
  export class FilteringHierarchyDefinition {
@@ -76,207 +78,142 @@ export class FilteringHierarchyDefinition {
76
78
  }
77
79
  get parseNode() {
78
80
  return async (row, parentNode) => {
79
- const hasFilterTargetAncestor = !!row[ECSQL_COLUMN_NAME_HasFilterTargetAncestor];
80
- const { filteredChildrenIdentifierPaths, filterTargetOptions, isFilterTarget } = row[ECSQL_COLUMN_NAME_FilterECInstanceId] && row[ECSQL_COLUMN_NAME_FilterClassName]
81
- ? await this.getChildrenIdentifierPaths(parentNode?.filtering?.filteredChildrenIdentifierPaths ?? this._nodeIdentifierPaths, {
82
- className: row[ECSQL_COLUMN_NAME_FilterClassName],
83
- id: row[ECSQL_COLUMN_NAME_FilterECInstanceId],
84
- })
85
- : { filteredChildrenIdentifierPaths: [], filterTargetOptions: undefined, isFilterTarget: false };
86
- const defaultNode = await (this._source.parseNode ?? defaultNodesParser)(row);
87
- return applyFilterAttributes({
88
- node: defaultNode,
89
- filteredChildrenIdentifierPaths,
90
- isFilterTarget,
91
- filterTargetOptions,
92
- hasFilterTargetAncestor,
93
- });
94
- };
95
- }
96
- async getChildrenIdentifierPaths(filteredChildrenNodeIdentifierPaths, providedIdentifier) {
97
- const { id, className } = providedIdentifier;
98
- let filteredChildrenIdentifierPaths;
99
- let isFilterTarget = false;
100
- let filterTargetOptions;
101
- for (const filteredChildrenNodeIdentifierPath of filteredChildrenNodeIdentifierPaths) {
102
- const { path, options } = HierarchyFilteringPath.normalize(filteredChildrenNodeIdentifierPath);
103
- /* c8 ignore next 3 */
104
- if (path.length === 0) {
105
- continue;
106
- }
107
- // We need to check if identifiers have the same id and imodelKey and are
108
- // of the same class / derived class / is derived from class
109
- const identifier = path[0];
110
- if (identifier.id !== id) {
111
- continue;
112
- }
113
- if (HierarchyNodeIdentifier.isInstanceNodeIdentifier(identifier)) {
114
- if (identifier.imodelKey && identifier.imodelKey !== this._imodelAccess.imodelKey) {
115
- continue;
116
- }
117
- if (identifier.className !== className &&
118
- !(await this._imodelAccess.classDerivesFrom(identifier.className, className)) &&
119
- !(await this._imodelAccess.classDerivesFrom(className, identifier.className))) {
120
- continue;
121
- }
122
- }
123
- if (!filteredChildrenIdentifierPaths) {
124
- filteredChildrenIdentifierPaths = [];
125
- }
126
- if (path.length > 1) {
127
- filteredChildrenIdentifierPaths.push(options ? { path: path.slice(1), options } : path.slice(1));
128
- }
129
- else if (isFilterTarget) {
130
- filterTargetOptions = HierarchyFilteringPath.mergeOptions(filterTargetOptions, options);
81
+ const parsedNode = await (this._source.parseNode ?? defaultNodesParser)(row);
82
+ const filteringHelper = createHierarchyFilteringHelper(this._nodeIdentifierPaths, parentNode);
83
+ const nodeExtraProps = row[ECSQL_COLUMN_NAME_FilterECInstanceId] && row[ECSQL_COLUMN_NAME_FilterClassName]
84
+ ? await (async () => {
85
+ const rowInstanceKey = { className: row[ECSQL_COLUMN_NAME_FilterClassName], id: row[ECSQL_COLUMN_NAME_FilterECInstanceId] };
86
+ return filteringHelper.createChildNodePropsAsync({
87
+ pathMatcher: (identifier) => {
88
+ if (identifier.id !== rowInstanceKey.id) {
89
+ return false;
90
+ }
91
+ if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(identifier)) {
92
+ return false;
93
+ }
94
+ if (identifier.imodelKey && identifier.imodelKey !== this._imodelAccess.imodelKey) {
95
+ return false;
96
+ }
97
+ if (identifier.className === rowInstanceKey.className) {
98
+ return true;
99
+ }
100
+ return Promise.all([
101
+ this._imodelAccess.classDerivesFrom(identifier.className, rowInstanceKey.className),
102
+ this._imodelAccess.classDerivesFrom(rowInstanceKey.className, identifier.className),
103
+ ]).then(([isDerivedFrom, isDerivedTo]) => isDerivedFrom || isDerivedTo);
104
+ },
105
+ });
106
+ })()
107
+ : undefined;
108
+ if (nodeExtraProps?.autoExpand) {
109
+ parsedNode.autoExpand = true;
131
110
  }
132
- else {
133
- isFilterTarget = true;
134
- filterTargetOptions = options;
111
+ if (nodeExtraProps?.filtering) {
112
+ parsedNode.filtering = nodeExtraProps.filtering;
135
113
  }
136
- }
137
- return { filteredChildrenIdentifierPaths, filterTargetOptions, isFilterTarget };
114
+ return parsedNode;
115
+ };
138
116
  }
139
117
  async defineHierarchyLevel(props) {
140
118
  const sourceDefinitions = await this._source.defineHierarchyLevel(props);
141
- const filteringProps = extractFilteringProps(this._nodeIdentifierPaths, props.parentNode);
142
- if (!filteringProps) {
119
+ const filteringHelper = createHierarchyFilteringHelper(this._nodeIdentifierPaths, props.parentNode);
120
+ const childNodeFilteringIdentifiers = filteringHelper.getChildNodeFilteringIdentifiers();
121
+ if (!childNodeFilteringIdentifiers) {
143
122
  return sourceDefinitions;
144
123
  }
145
- const filteredDefinitions = [];
146
- await Promise.all(sourceDefinitions.map(async (definition) => {
147
- let matchedDefinition;
148
- if (HierarchyNodesDefinition.isGenericNode(definition)) {
149
- matchedDefinition = await matchFilters(definition, filteringProps, async (id) => {
150
- return (HierarchyNodeIdentifier.isGenericNodeIdentifier(id) &&
151
- (!id.source || id.source === this._imodelAccess.imodelKey) &&
152
- id.id === definition.node.key);
153
- }, this._imodelAccess, (def, matchingFilters) => {
154
- const filteredChildrenIdentifierPaths = matchingFilters.reduce((r, c) => [...r, ...c.childrenIdentifierPaths], new Array());
155
- return {
156
- ...def,
157
- node: applyFilterAttributes({
158
- node: def.node,
159
- filteredChildrenIdentifierPaths,
160
- isFilterTarget: matchingFilters.some((mc) => mc.isFilterTarget),
161
- filterTargetOptions: matchingFilters.find((mc) => mc.isFilterTarget)?.filterTargetOptions,
162
- hasFilterTargetAncestor: filteringProps.hasFilterTargetAncestor,
163
- }),
164
- };
165
- });
166
- }
167
- else {
168
- matchedDefinition = await matchFilters(definition, filteringProps, async (id) => {
169
- return (HierarchyNodeIdentifier.isInstanceNodeIdentifier(id) &&
170
- (!id.imodelKey || id.imodelKey === this._imodelAccess.imodelKey) &&
171
- (await this._imodelAccess.classDerivesFrom(id.className, definition.fullClassName)));
172
- }, this._imodelAccess, (def, matchingFilters) => applyECInstanceIdsFilter(def, matchingFilters, !!filteringProps.hasFilterTargetAncestor), false);
173
- }
174
- if (matchedDefinition) {
175
- filteredDefinitions.push(matchedDefinition);
176
- }
177
- }));
178
- return filteredDefinitions;
179
- }
180
- }
181
- async function matchFilters(definition, filteringProps, predicate, classHierarchy, matchedDefinitionProcessor, extractPathsAndOptions = true) {
182
- const { filteredNodePaths, hasFilterTargetAncestor } = filteringProps;
183
- const matchingFilters = [];
184
- for (const filteredNodePath of filteredNodePaths) {
185
- const { path, options } = HierarchyFilteringPath.normalize(filteredNodePath);
186
- if (path.length === 0) {
187
- continue;
188
- }
189
- const nodeId = path[0];
190
- if (await predicate(nodeId)) {
191
- let entry = await findMatchingFilterEntry(matchingFilters, nodeId, classHierarchy);
192
- if (!entry) {
193
- entry = {
194
- // ideally, `predicate` would act as a type guard to guarantee that `id` is `TIdentifier`, but at the moment
195
- // async type guards aren't supported
196
- id: nodeId,
197
- childrenIdentifierPaths: [],
198
- isFilterTarget: false,
124
+ const [genericNodeDefinitions, instanceNodeDefinitions] = partition(sourceDefinitions, HierarchyNodesDefinition.isGenericNode);
125
+ return firstValueFrom(merge(genericNodeDefinitions.pipe(map((definition) => {
126
+ if (filteringHelper.hasFilterTargetAncestor ||
127
+ childNodeFilteringIdentifiers.some((identifier) => HierarchyNodeIdentifier.isGenericNodeIdentifier(identifier) &&
128
+ (!identifier.source || identifier.source === this._imodelAccess.imodelKey) &&
129
+ identifier.id === definition.node.key)) {
130
+ return {
131
+ ...definition,
132
+ node: {
133
+ ...definition.node,
134
+ ...filteringHelper.createChildNodeProps({ pathMatcher: ({ id }) => id === definition.node.key }),
135
+ },
199
136
  };
200
- matchingFilters.push(entry);
201
- }
202
- if (!extractPathsAndOptions) {
203
- continue;
204
- }
205
- if (path.length > 1) {
206
- entry.childrenIdentifierPaths.push(options ? { path: path.slice(1), options } : path.slice(1));
207
- }
208
- else if (entry.isFilterTarget) {
209
- entry.filterTargetOptions = HierarchyFilteringPath.mergeOptions(entry.filterTargetOptions, options);
210
137
  }
211
- else {
212
- Object.assign(entry, { isFilterTarget: true, filterTargetOptions: options });
138
+ return undefined;
139
+ }), filter((def) => !!def)), instanceNodeDefinitions.pipe(mergeMap((definition) => {
140
+ if (filteringHelper.hasFilterTargetAncestor) {
141
+ // if we have a filter target ancestor, we don't need to filter the definitions - we use all of them
142
+ return of(applyECInstanceIdsSelector(definition));
213
143
  }
214
- }
215
- }
216
- if (hasFilterTargetAncestor || matchingFilters.length > 0) {
217
- return matchedDefinitionProcessor(definition, matchingFilters);
218
- }
219
- return undefined;
220
- }
221
- async function findMatchingFilterEntry(filters, nodeId, classHierarchy) {
222
- for (const filter of filters) {
223
- if (await identifiersEqual(filter.id, nodeId, classHierarchy)) {
224
- return filter;
225
- }
226
- }
227
- return undefined;
228
- }
229
- async function identifiersEqual(lhs, rhs, classHierarchy) {
230
- if (HierarchyNodeIdentifier.isInstanceNodeIdentifier(lhs) && HierarchyNodeIdentifier.isInstanceNodeIdentifier(rhs)) {
231
- return (lhs.id === rhs.id &&
232
- (lhs.className === rhs.className ||
233
- (await classHierarchy.classDerivesFrom(lhs.className, rhs.className)) ||
234
- (await classHierarchy.classDerivesFrom(rhs.className, lhs.className))));
235
- }
236
- return HierarchyNodeIdentifier.equal(lhs, rhs);
237
- }
238
- function applyFilterAttributes(props) {
239
- const { node, filteredChildrenIdentifierPaths } = props;
240
- const result = { ...node };
241
- const shouldAutoExpand = !!filteredChildrenIdentifierPaths?.some((childPath) => {
242
- return !!HierarchyFilteringPath.normalize(childPath).options?.autoExpand;
243
- });
244
- if (shouldAutoExpand) {
245
- result.autoExpand = true;
246
- }
247
- const filteringProps = HierarchyNodeFilteringProps.create(props);
248
- if (filteringProps) {
249
- result.filtering = filteringProps;
144
+ return defer(async () => {
145
+ const imodelAccess = this._imodelAccess;
146
+ const matches = new Map();
147
+ async function getEntries(x) {
148
+ let entries = matches.get(x.id);
149
+ if (!entries) {
150
+ entries = [];
151
+ matches.set(x.id, entries);
152
+ }
153
+ // make sure that we don't have path identifiers that only differ by class name, where
154
+ // class names are in the same class hierarchy, e.g.:
155
+ // [{ className: "bis.Element", id: "0x1" }, { className: "bis.Subject", id: "0x1" }]
156
+ // are actually the same instance, so we only need to keep one of them, or otherwise the query will
157
+ // duplicate it
158
+ for (const entry of entries) {
159
+ if (entry.className === x.className ||
160
+ (await imodelAccess.classDerivesFrom(entry.className, x.className)) ||
161
+ (await imodelAccess.classDerivesFrom(x.className, entry.className))) {
162
+ return undefined;
163
+ }
164
+ }
165
+ return entries;
166
+ }
167
+ for (const id of childNodeFilteringIdentifiers) {
168
+ // take only identifiers that match the definition by type, source and class
169
+ if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(id)) {
170
+ continue;
171
+ }
172
+ if (id.imodelKey && id.imodelKey !== imodelAccess.imodelKey) {
173
+ continue;
174
+ }
175
+ if (id.className !== definition.fullClassName &&
176
+ !(await Promise.all([
177
+ imodelAccess.classDerivesFrom(id.className, definition.fullClassName),
178
+ imodelAccess.classDerivesFrom(definition.fullClassName, id.className),
179
+ ]).then(([isDerivedFrom, isDerivedTo]) => isDerivedFrom || isDerivedTo))) {
180
+ continue;
181
+ }
182
+ const entriesTargetForPathIdentifier = await getEntries(id);
183
+ if (entriesTargetForPathIdentifier) {
184
+ entriesTargetForPathIdentifier.push(id);
185
+ }
186
+ }
187
+ return Array.from(matches.values()).flat();
188
+ }).pipe(
189
+ // only take definitions that have matching path identifiers
190
+ filter((pathIdentifiers) => pathIdentifiers.length > 0),
191
+ // for each definition that we're going to use, apply query-level filter
192
+ map((pathIdentifiers) => applyECInstanceIdsFilter(definition, pathIdentifiers)));
193
+ }))).pipe(toArray()));
250
194
  }
251
- return result;
252
195
  }
253
196
  /** @internal */
254
197
  // eslint-disable-next-line @typescript-eslint/naming-convention
255
- export const ECSQL_COLUMN_NAME_HasFilterTargetAncestor = "HasFilterTargetAncestor";
256
- /** @internal */
257
- // eslint-disable-next-line @typescript-eslint/naming-convention
258
198
  export const ECSQL_COLUMN_NAME_FilterECInstanceId = "FilterECInstanceId";
259
199
  /** @internal */
260
200
  // eslint-disable-next-line @typescript-eslint/naming-convention
261
201
  export const ECSQL_COLUMN_NAME_FilterClassName = "FilterClassName";
262
- function getClassECInstanceIds(matchingFilters) {
202
+ function getClassECInstanceIds(filteredInstanceKeys) {
263
203
  const classNameECInstanceIds = new Map();
264
- for (const matchingFilter of matchingFilters) {
265
- const entry = classNameECInstanceIds.get(matchingFilter.id.className);
204
+ for (const key of filteredInstanceKeys) {
205
+ const entry = classNameECInstanceIds.get(key.className);
266
206
  if (entry === undefined) {
267
- classNameECInstanceIds.set(matchingFilter.id.className, [matchingFilter.id.id]);
207
+ classNameECInstanceIds.set(key.className, [key.id]);
268
208
  continue;
269
209
  }
270
- entry.push(matchingFilter.id.id);
210
+ entry.push(key.id);
271
211
  }
272
212
  return classNameECInstanceIds;
273
213
  }
274
214
  /** @internal */
275
- export function applyECInstanceIdsFilter(def, matchingFilters, hasFilterTargetAncestor) {
276
- if (matchingFilters.length === 0) {
277
- return def;
278
- }
279
- const matchingFiltersToUse = getClassECInstanceIds(matchingFilters);
215
+ export function applyECInstanceIdsFilter(def, filteredInstanceKeys) {
216
+ const instanceIdsByClass = getClassECInstanceIds(filteredInstanceKeys);
280
217
  return {
281
218
  ...def,
282
219
  query: {
@@ -284,7 +221,7 @@ export function applyECInstanceIdsFilter(def, matchingFilters, hasFilterTargetAn
284
221
  ctes: [
285
222
  ...(def.query.ctes ?? []),
286
223
  `FilteringInfo(ECInstanceId, FilterClassName) AS (
287
- ${Array.from(matchingFiltersToUse)
224
+ ${Array.from(instanceIdsByClass)
288
225
  .map(([className, ecInstanceIds]) => `
289
226
  SELECT ECInstanceId, '${className}' AS FilterClassName
290
227
  FROM ${className}
@@ -296,13 +233,28 @@ export function applyECInstanceIdsFilter(def, matchingFilters, hasFilterTargetAn
296
233
  ecsql: `
297
234
  SELECT
298
235
  [q].*,
299
- ${hasFilterTargetAncestor ? "1" : "0"} AS [${ECSQL_COLUMN_NAME_HasFilterTargetAncestor}],
300
236
  IdToHex([f].[ECInstanceId]) AS [${ECSQL_COLUMN_NAME_FilterECInstanceId}],
301
237
  [f].[FilterClassName] AS [${ECSQL_COLUMN_NAME_FilterClassName}]
302
238
  FROM (
303
239
  ${def.query.ecsql}
304
240
  ) [q]
305
- ${hasFilterTargetAncestor ? "LEFT " : ""} JOIN FilteringInfo [f] ON [f].[ECInstanceId] = [q].[ECInstanceId]
241
+ JOIN FilteringInfo [f] ON [f].[ECInstanceId] = [q].[ECInstanceId]
242
+ `,
243
+ },
244
+ };
245
+ }
246
+ /** @internal */
247
+ export function applyECInstanceIdsSelector(def) {
248
+ return {
249
+ ...def,
250
+ query: {
251
+ ...def.query,
252
+ ecsql: `
253
+ SELECT
254
+ [q].*,
255
+ IdToHex([q].[ECInstanceId]) AS [${ECSQL_COLUMN_NAME_FilterECInstanceId}],
256
+ [q].[${NodeSelectClauseColumnNames.FullClassName}] AS [${ECSQL_COLUMN_NAME_FilterClassName}]
257
+ FROM (${def.query.ecsql}) [q]
306
258
  `,
307
259
  },
308
260
  };
@@ -1 +1 @@
1
- {"version":3,"file":"FilteringHierarchyDefinition.js","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/FilteringHierarchyDefinition.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 { Id64String } from \"@itwin/core-bentley\";\nimport { ECClassHierarchyInspector, InstanceKey } from \"@itwin/presentation-shared\";\nimport { extractFilteringProps, HierarchyFilteringPath, HierarchyFilteringPathOptions } from \"../HierarchyFiltering.js\";\nimport { HierarchyNodeFilteringProps } from \"../HierarchyNode.js\";\nimport { HierarchyNodeIdentifier } from \"../HierarchyNodeIdentifier.js\";\nimport { GenericNodeKey } from \"../HierarchyNodeKey.js\";\nimport {\n DefineHierarchyLevelProps,\n GenericHierarchyNodeDefinition,\n HierarchyDefinition,\n HierarchyDefinitionParentNode,\n HierarchyLevelDefinition,\n HierarchyNodesDefinition,\n InstanceNodesQueryDefinition,\n NodeParser,\n NodePostProcessor,\n NodePreProcessor,\n} from \"./IModelHierarchyDefinition.js\";\nimport { ProcessedGroupingHierarchyNode, ProcessedHierarchyNode, SourceHierarchyNode, SourceInstanceHierarchyNode } from \"./IModelHierarchyNode.js\";\nimport { defaultNodesParser } from \"./TreeNodesReader.js\";\n\ninterface FilteringHierarchyDefinitionProps {\n imodelAccess: ECClassHierarchyInspector & { imodelKey: string };\n source: HierarchyDefinition;\n nodeIdentifierPaths: HierarchyFilteringPath[];\n}\n\n/** @internal */\nexport class FilteringHierarchyDefinition implements HierarchyDefinition {\n private _imodelAccess: ECClassHierarchyInspector & { imodelKey: string };\n private _source: HierarchyDefinition;\n private _nodeIdentifierPaths: HierarchyFilteringPath[];\n\n public constructor(props: FilteringHierarchyDefinitionProps) {\n this._imodelAccess = props.imodelAccess;\n this._source = props.source;\n this._nodeIdentifierPaths = props.nodeIdentifierPaths;\n }\n\n public get preProcessNode(): NodePreProcessor {\n return async (node) => {\n const processedNode = this._source.preProcessNode ? await this._source.preProcessNode(node) : node;\n if (processedNode?.processingParams?.hideInHierarchy && processedNode.filtering?.isFilterTarget && !processedNode.filtering.hasFilterTargetAncestor) {\n // we want to hide target nodes if they have `hideInHierarchy` param, but only if they're not under another filter target\n return undefined;\n }\n return processedNode;\n };\n }\n\n private shouldExpandGroupingNode(node: ProcessedGroupingHierarchyNode) {\n for (const child of node.children) {\n /* c8 ignore next 3 */\n if (!child.filtering) {\n continue;\n }\n\n if (child.filtering.isFilterTarget) {\n const childAutoExpand = child.filtering.filterTargetOptions?.autoExpand;\n\n // If child is a filter target and is has no `autoExpand` flag, then it's always to be expanded.\n if (childAutoExpand === true) {\n return true;\n }\n\n // If it's not an object and not `true`, then it's falsy - continue looking\n if (typeof childAutoExpand !== \"object\") {\n continue;\n }\n\n // If grouping node's child has `autoExpandUntil` flag,\n // auto-expand the grouping node only if it's depth is lower than that of the grouping node in associated with the target.\n const nodeDepth = node.parentKeys.length;\n const filterTargetDepth = childAutoExpand.depth;\n if (nodeDepth < filterTargetDepth) {\n return true;\n }\n }\n\n if (!child.filtering.filteredChildrenIdentifierPaths) {\n /* c8 ignore next */\n continue;\n }\n\n for (const path of child.filtering.filteredChildrenIdentifierPaths) {\n if (\"path\" in path && path.options?.autoExpand) {\n return true;\n }\n }\n }\n return false;\n }\n\n public get postProcessNode(): NodePostProcessor {\n return async (node: ProcessedHierarchyNode) => {\n const processedNode = this._source.postProcessNode ? await this._source.postProcessNode(node) : node;\n // instance nodes get the auto-expand flag in `parseNode`, but grouping ones need to be handled during post-processing\n if (ProcessedHierarchyNode.isGroupingNode(node) && this.shouldExpandGroupingNode(node)) {\n Object.assign(processedNode, { autoExpand: true });\n }\n return processedNode;\n };\n }\n\n public get parseNode(): NodeParser {\n return async (row: { [columnName: string]: any }, parentNode?: HierarchyDefinitionParentNode): Promise<SourceInstanceHierarchyNode> => {\n const hasFilterTargetAncestor: boolean = !!row[ECSQL_COLUMN_NAME_HasFilterTargetAncestor];\n\n const { filteredChildrenIdentifierPaths, filterTargetOptions, isFilterTarget } =\n row[ECSQL_COLUMN_NAME_FilterECInstanceId] && row[ECSQL_COLUMN_NAME_FilterClassName]\n ? await this.getChildrenIdentifierPaths(parentNode?.filtering?.filteredChildrenIdentifierPaths ?? this._nodeIdentifierPaths, {\n className: row[ECSQL_COLUMN_NAME_FilterClassName],\n id: row[ECSQL_COLUMN_NAME_FilterECInstanceId],\n })\n : { filteredChildrenIdentifierPaths: [], filterTargetOptions: undefined, isFilterTarget: false };\n\n const defaultNode = await (this._source.parseNode ?? defaultNodesParser)(row);\n return applyFilterAttributes({\n node: defaultNode,\n filteredChildrenIdentifierPaths,\n isFilterTarget,\n filterTargetOptions,\n hasFilterTargetAncestor,\n });\n };\n }\n\n private async getChildrenIdentifierPaths(filteredChildrenNodeIdentifierPaths: HierarchyFilteringPath[], providedIdentifier: InstanceKey) {\n const { id, className } = providedIdentifier;\n\n let filteredChildrenIdentifierPaths: HierarchyFilteringPath[] | undefined;\n let isFilterTarget = false;\n let filterTargetOptions: HierarchyFilteringPathOptions | undefined;\n for (const filteredChildrenNodeIdentifierPath of filteredChildrenNodeIdentifierPaths) {\n const { path, options } = HierarchyFilteringPath.normalize(filteredChildrenNodeIdentifierPath);\n /* c8 ignore next 3 */\n if (path.length === 0) {\n continue;\n }\n\n // We need to check if identifiers have the same id and imodelKey and are\n // of the same class / derived class / is derived from class\n const identifier = path[0];\n if (identifier.id !== id) {\n continue;\n }\n if (HierarchyNodeIdentifier.isInstanceNodeIdentifier(identifier)) {\n if (identifier.imodelKey && identifier.imodelKey !== this._imodelAccess.imodelKey) {\n continue;\n }\n if (\n identifier.className !== className &&\n !(await this._imodelAccess.classDerivesFrom(identifier.className, className)) &&\n !(await this._imodelAccess.classDerivesFrom(className, identifier.className))\n ) {\n continue;\n }\n }\n if (!filteredChildrenIdentifierPaths) {\n filteredChildrenIdentifierPaths = [];\n }\n if (path.length > 1) {\n filteredChildrenIdentifierPaths.push(options ? { path: path.slice(1), options } : path.slice(1));\n } else if (isFilterTarget) {\n filterTargetOptions = HierarchyFilteringPath.mergeOptions(filterTargetOptions, options);\n } else {\n isFilterTarget = true;\n filterTargetOptions = options;\n }\n }\n return { filteredChildrenIdentifierPaths, filterTargetOptions, isFilterTarget };\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const sourceDefinitions = await this._source.defineHierarchyLevel(props);\n const filteringProps = extractFilteringProps(this._nodeIdentifierPaths, props.parentNode);\n if (!filteringProps) {\n return sourceDefinitions;\n }\n\n const filteredDefinitions: HierarchyLevelDefinition = [];\n await Promise.all(\n sourceDefinitions.map(async (definition) => {\n let matchedDefinition: HierarchyNodesDefinition | undefined;\n if (HierarchyNodesDefinition.isGenericNode(definition)) {\n matchedDefinition = await matchFilters<GenericNodeKey>(\n definition,\n filteringProps,\n async (id) => {\n return (\n HierarchyNodeIdentifier.isGenericNodeIdentifier(id) &&\n (!id.source || id.source === this._imodelAccess.imodelKey) &&\n id.id === definition.node.key\n );\n },\n this._imodelAccess,\n (def, matchingFilters) => {\n const filteredChildrenIdentifierPaths = matchingFilters.reduce(\n (r, c) => [...r, ...c.childrenIdentifierPaths],\n new Array<HierarchyFilteringPath>(),\n );\n return {\n ...def,\n node: applyFilterAttributes({\n node: def.node,\n filteredChildrenIdentifierPaths,\n isFilterTarget: matchingFilters.some((mc) => mc.isFilterTarget),\n filterTargetOptions: matchingFilters.find((mc) => mc.isFilterTarget)?.filterTargetOptions,\n hasFilterTargetAncestor: filteringProps.hasFilterTargetAncestor,\n }),\n };\n },\n );\n } else {\n matchedDefinition = await matchFilters<InstanceKey>(\n definition,\n filteringProps,\n async (id) => {\n return (\n HierarchyNodeIdentifier.isInstanceNodeIdentifier(id) &&\n (!id.imodelKey || id.imodelKey === this._imodelAccess.imodelKey) &&\n (await this._imodelAccess.classDerivesFrom(id.className, definition.fullClassName))\n );\n },\n this._imodelAccess,\n (def, matchingFilters) => applyECInstanceIdsFilter(def, matchingFilters, !!filteringProps.hasFilterTargetAncestor),\n false,\n );\n }\n if (matchedDefinition) {\n filteredDefinitions.push(matchedDefinition);\n }\n }),\n );\n return filteredDefinitions;\n }\n}\n\ntype MatchedFilter<TIdentifier extends HierarchyNodeIdentifier> = {\n id: TIdentifier;\n childrenIdentifierPaths: HierarchyFilteringPath[];\n} & ({ isFilterTarget: false } | { isFilterTarget: true; filterTargetOptions?: HierarchyFilteringPathOptions });\n\nasync function matchFilters<\n TIdentifier extends HierarchyNodeIdentifier,\n TDefinition = TIdentifier extends InstanceKey ? InstanceNodesQueryDefinition : GenericHierarchyNodeDefinition,\n>(\n definition: TDefinition,\n filteringProps: { filteredNodePaths: HierarchyFilteringPath[]; hasFilterTargetAncestor?: boolean },\n predicate: (id: HierarchyNodeIdentifier) => Promise<boolean>,\n classHierarchy: ECClassHierarchyInspector,\n matchedDefinitionProcessor: (def: TDefinition, matchingFilters: Array<MatchedFilter<TIdentifier>>) => TDefinition,\n extractPathsAndOptions: boolean = true,\n): Promise<TDefinition | undefined> {\n const { filteredNodePaths, hasFilterTargetAncestor } = filteringProps;\n const matchingFilters: Array<MatchedFilter<TIdentifier>> = [];\n for (const filteredNodePath of filteredNodePaths) {\n const { path, options } = HierarchyFilteringPath.normalize(filteredNodePath);\n if (path.length === 0) {\n continue;\n }\n const nodeId = path[0];\n if (await predicate(nodeId)) {\n let entry = await findMatchingFilterEntry(matchingFilters, nodeId, classHierarchy);\n if (!entry) {\n entry = {\n // ideally, `predicate` would act as a type guard to guarantee that `id` is `TIdentifier`, but at the moment\n // async type guards aren't supported\n id: nodeId as TIdentifier,\n childrenIdentifierPaths: [],\n isFilterTarget: false,\n };\n matchingFilters.push(entry);\n }\n\n if (!extractPathsAndOptions) {\n continue;\n }\n\n if (path.length > 1) {\n entry.childrenIdentifierPaths.push(options ? { path: path.slice(1), options } : path.slice(1));\n } else if (entry.isFilterTarget) {\n entry.filterTargetOptions = HierarchyFilteringPath.mergeOptions(entry.filterTargetOptions, options);\n } else {\n Object.assign(entry, { isFilterTarget: true, filterTargetOptions: options });\n }\n }\n }\n if (hasFilterTargetAncestor || matchingFilters.length > 0) {\n return matchedDefinitionProcessor(definition, matchingFilters);\n }\n return undefined;\n}\n\nasync function findMatchingFilterEntry<TEntry extends { id: TIdentifier }, TIdentifier extends HierarchyNodeIdentifier>(\n filters: TEntry[],\n nodeId: TIdentifier,\n classHierarchy: ECClassHierarchyInspector,\n): Promise<TEntry | undefined> {\n for (const filter of filters) {\n if (await identifiersEqual(filter.id, nodeId, classHierarchy)) {\n return filter;\n }\n }\n return undefined;\n}\n\nasync function identifiersEqual<TIdentifier extends HierarchyNodeIdentifier>(lhs: TIdentifier, rhs: TIdentifier, classHierarchy: ECClassHierarchyInspector) {\n if (HierarchyNodeIdentifier.isInstanceNodeIdentifier(lhs) && HierarchyNodeIdentifier.isInstanceNodeIdentifier(rhs)) {\n return (\n lhs.id === rhs.id &&\n (lhs.className === rhs.className ||\n (await classHierarchy.classDerivesFrom(lhs.className, rhs.className)) ||\n (await classHierarchy.classDerivesFrom(rhs.className, lhs.className)))\n );\n }\n return HierarchyNodeIdentifier.equal(lhs, rhs);\n}\n\nfunction applyFilterAttributes<TNode extends SourceHierarchyNode>(props: {\n node: TNode;\n filteredChildrenIdentifierPaths: HierarchyFilteringPath[] | undefined;\n isFilterTarget?: boolean;\n filterTargetOptions?: HierarchyFilteringPathOptions;\n hasFilterTargetAncestor: boolean;\n}): TNode {\n const { node, filteredChildrenIdentifierPaths } = props;\n const result = { ...node };\n\n const shouldAutoExpand = !!filteredChildrenIdentifierPaths?.some((childPath) => {\n return !!HierarchyFilteringPath.normalize(childPath).options?.autoExpand;\n });\n if (shouldAutoExpand) {\n result.autoExpand = true;\n }\n\n const filteringProps = HierarchyNodeFilteringProps.create(props);\n if (filteringProps) {\n result.filtering = filteringProps;\n }\n\n return result;\n}\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_HasFilterTargetAncestor = \"HasFilterTargetAncestor\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_FilterECInstanceId = \"FilterECInstanceId\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_FilterClassName = \"FilterClassName\";\n\nfunction getClassECInstanceIds(matchingFilters: Array<{ id: InstanceKey }>) {\n const classNameECInstanceIds = new Map<string, Id64String[]>();\n for (const matchingFilter of matchingFilters) {\n const entry = classNameECInstanceIds.get(matchingFilter.id.className);\n if (entry === undefined) {\n classNameECInstanceIds.set(matchingFilter.id.className, [matchingFilter.id.id]);\n continue;\n }\n entry.push(matchingFilter.id.id);\n }\n return classNameECInstanceIds;\n}\n\n/** @internal */\nexport function applyECInstanceIdsFilter(\n def: InstanceNodesQueryDefinition,\n matchingFilters: Array<{ id: InstanceKey }>,\n hasFilterTargetAncestor: boolean,\n): InstanceNodesQueryDefinition {\n if (matchingFilters.length === 0) {\n return def;\n }\n const matchingFiltersToUse = getClassECInstanceIds(matchingFilters);\n return {\n ...def,\n query: {\n ...def.query,\n ctes: [\n ...(def.query.ctes ?? []),\n `FilteringInfo(ECInstanceId, FilterClassName) AS (\n ${Array.from(matchingFiltersToUse)\n .map(\n ([className, ecInstanceIds]) => `\n SELECT ECInstanceId, '${className}' AS FilterClassName\n FROM ${className}\n WHERE ECInstanceId IN (${ecInstanceIds.join(\", \")})\n `,\n )\n .join(\" UNION ALL \")}\n )`,\n ],\n ecsql: `\n SELECT\n [q].*,\n ${hasFilterTargetAncestor ? \"1\" : \"0\"} AS [${ECSQL_COLUMN_NAME_HasFilterTargetAncestor}],\n IdToHex([f].[ECInstanceId]) AS [${ECSQL_COLUMN_NAME_FilterECInstanceId}],\n [f].[FilterClassName] AS [${ECSQL_COLUMN_NAME_FilterClassName}]\n FROM (\n ${def.query.ecsql}\n ) [q]\n ${hasFilterTargetAncestor ? \"LEFT \" : \"\"} JOIN FilteringInfo [f] ON [f].[ECInstanceId] = [q].[ECInstanceId]\n `,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"FilteringHierarchyDefinition.js","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/FilteringHierarchyDefinition.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 { defer, filter, firstValueFrom, map, merge, mergeMap, of, toArray } from \"rxjs\";\nimport { Id64String } from \"@itwin/core-bentley\";\nimport { ECClassHierarchyInspector, InstanceKey } from \"@itwin/presentation-shared\";\nimport { createHierarchyFilteringHelper, HierarchyFilteringPath } from \"../HierarchyFiltering.js\";\nimport { HierarchyNodeIdentifier } from \"../HierarchyNodeIdentifier.js\";\nimport { IModelInstanceKey } from \"../HierarchyNodeKey.js\";\nimport { partition } from \"../internal/operators/Partition.js\";\nimport {\n DefineHierarchyLevelProps,\n GenericHierarchyNodeDefinition,\n HierarchyDefinition,\n HierarchyDefinitionParentNode,\n HierarchyLevelDefinition,\n HierarchyNodesDefinition,\n InstanceNodesQueryDefinition,\n NodeParser,\n NodePostProcessor,\n NodePreProcessor,\n} from \"./IModelHierarchyDefinition.js\";\nimport { ProcessedGroupingHierarchyNode, ProcessedHierarchyNode, SourceInstanceHierarchyNode } from \"./IModelHierarchyNode.js\";\nimport { NodeSelectClauseColumnNames } from \"./NodeSelectQueryFactory.js\";\nimport { defaultNodesParser } from \"./TreeNodesReader.js\";\n\ninterface FilteringHierarchyDefinitionProps {\n imodelAccess: ECClassHierarchyInspector & { imodelKey: string };\n source: HierarchyDefinition;\n nodeIdentifierPaths: HierarchyFilteringPath[];\n}\n\n/** @internal */\nexport class FilteringHierarchyDefinition implements HierarchyDefinition {\n private _imodelAccess: ECClassHierarchyInspector & { imodelKey: string };\n private _source: HierarchyDefinition;\n private _nodeIdentifierPaths: HierarchyFilteringPath[];\n\n public constructor(props: FilteringHierarchyDefinitionProps) {\n this._imodelAccess = props.imodelAccess;\n this._source = props.source;\n this._nodeIdentifierPaths = props.nodeIdentifierPaths;\n }\n\n public get preProcessNode(): NodePreProcessor {\n return async (node) => {\n const processedNode = this._source.preProcessNode ? await this._source.preProcessNode(node) : node;\n if (processedNode?.processingParams?.hideInHierarchy && processedNode.filtering?.isFilterTarget && !processedNode.filtering.hasFilterTargetAncestor) {\n // we want to hide target nodes if they have `hideInHierarchy` param, but only if they're not under another filter target\n return undefined;\n }\n return processedNode;\n };\n }\n\n private shouldExpandGroupingNode(node: ProcessedGroupingHierarchyNode) {\n for (const child of node.children) {\n /* c8 ignore next 3 */\n if (!child.filtering) {\n continue;\n }\n\n if (child.filtering.isFilterTarget) {\n const childAutoExpand = child.filtering.filterTargetOptions?.autoExpand;\n\n // If child is a filter target and is has no `autoExpand` flag, then it's always to be expanded.\n if (childAutoExpand === true) {\n return true;\n }\n\n // If it's not an object and not `true`, then it's falsy - continue looking\n if (typeof childAutoExpand !== \"object\") {\n continue;\n }\n\n // If grouping node's child has `autoExpandUntil` flag,\n // auto-expand the grouping node only if it's depth is lower than that of the grouping node in associated with the target.\n const nodeDepth = node.parentKeys.length;\n const filterTargetDepth = childAutoExpand.depth;\n if (nodeDepth < filterTargetDepth) {\n return true;\n }\n }\n\n if (!child.filtering.filteredChildrenIdentifierPaths) {\n /* c8 ignore next */\n continue;\n }\n\n for (const path of child.filtering.filteredChildrenIdentifierPaths) {\n if (\"path\" in path && path.options?.autoExpand) {\n return true;\n }\n }\n }\n return false;\n }\n\n public get postProcessNode(): NodePostProcessor {\n return async (node: ProcessedHierarchyNode) => {\n const processedNode = this._source.postProcessNode ? await this._source.postProcessNode(node) : node;\n // instance nodes get the auto-expand flag in `parseNode`, but grouping ones need to be handled during post-processing\n if (ProcessedHierarchyNode.isGroupingNode(node) && this.shouldExpandGroupingNode(node)) {\n Object.assign(processedNode, { autoExpand: true });\n }\n return processedNode;\n };\n }\n\n public get parseNode(): NodeParser {\n return async (row: { [columnName: string]: any }, parentNode?: HierarchyDefinitionParentNode): Promise<SourceInstanceHierarchyNode> => {\n const parsedNode = await (this._source.parseNode ?? defaultNodesParser)(row);\n\n const filteringHelper = createHierarchyFilteringHelper(this._nodeIdentifierPaths, parentNode);\n const nodeExtraProps =\n row[ECSQL_COLUMN_NAME_FilterECInstanceId] && row[ECSQL_COLUMN_NAME_FilterClassName]\n ? await (async () => {\n const rowInstanceKey = { className: row[ECSQL_COLUMN_NAME_FilterClassName], id: row[ECSQL_COLUMN_NAME_FilterECInstanceId] };\n return filteringHelper.createChildNodePropsAsync({\n pathMatcher: (identifier): boolean | Promise<boolean> => {\n if (identifier.id !== rowInstanceKey.id) {\n return false;\n }\n if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(identifier)) {\n return false;\n }\n if (identifier.imodelKey && identifier.imodelKey !== this._imodelAccess.imodelKey) {\n return false;\n }\n if (identifier.className === rowInstanceKey.className) {\n return true;\n }\n return Promise.all([\n this._imodelAccess.classDerivesFrom(identifier.className, rowInstanceKey.className),\n this._imodelAccess.classDerivesFrom(rowInstanceKey.className, identifier.className),\n ]).then(([isDerivedFrom, isDerivedTo]) => isDerivedFrom || isDerivedTo);\n },\n });\n })()\n : undefined;\n if (nodeExtraProps?.autoExpand) {\n parsedNode.autoExpand = true;\n }\n if (nodeExtraProps?.filtering) {\n parsedNode.filtering = nodeExtraProps.filtering;\n }\n\n return parsedNode;\n };\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const sourceDefinitions = await this._source.defineHierarchyLevel(props);\n\n const filteringHelper = createHierarchyFilteringHelper(this._nodeIdentifierPaths, props.parentNode);\n const childNodeFilteringIdentifiers = filteringHelper.getChildNodeFilteringIdentifiers();\n if (!childNodeFilteringIdentifiers) {\n return sourceDefinitions;\n }\n\n const [genericNodeDefinitions, instanceNodeDefinitions] = partition(sourceDefinitions, HierarchyNodesDefinition.isGenericNode);\n return firstValueFrom(\n merge(\n genericNodeDefinitions.pipe(\n map((definition) => {\n if (\n filteringHelper.hasFilterTargetAncestor ||\n childNodeFilteringIdentifiers.some(\n (identifier) =>\n HierarchyNodeIdentifier.isGenericNodeIdentifier(identifier) &&\n (!identifier.source || identifier.source === this._imodelAccess.imodelKey) &&\n identifier.id === definition.node.key,\n )\n ) {\n return {\n ...definition,\n node: {\n ...definition.node,\n ...filteringHelper.createChildNodeProps({ pathMatcher: ({ id }) => id === definition.node.key }),\n },\n };\n }\n return undefined;\n }),\n filter((def): def is GenericHierarchyNodeDefinition => !!def),\n ),\n\n instanceNodeDefinitions.pipe(\n mergeMap((definition) => {\n if (filteringHelper.hasFilterTargetAncestor) {\n // if we have a filter target ancestor, we don't need to filter the definitions - we use all of them\n return of(applyECInstanceIdsSelector(definition));\n }\n return defer(async () => {\n const imodelAccess = this._imodelAccess;\n const matches = new Map<Id64String, IModelInstanceKey[]>();\n async function getEntries(x: IModelInstanceKey) {\n let entries = matches.get(x.id);\n if (!entries) {\n entries = [];\n matches.set(x.id, entries);\n }\n // make sure that we don't have path identifiers that only differ by class name, where\n // class names are in the same class hierarchy, e.g.:\n // [{ className: \"bis.Element\", id: \"0x1\" }, { className: \"bis.Subject\", id: \"0x1\" }]\n // are actually the same instance, so we only need to keep one of them, or otherwise the query will\n // duplicate it\n for (const entry of entries) {\n if (\n entry.className === x.className ||\n (await imodelAccess.classDerivesFrom(entry.className, x.className)) ||\n (await imodelAccess.classDerivesFrom(x.className, entry.className))\n ) {\n return undefined;\n }\n }\n return entries;\n }\n for (const id of childNodeFilteringIdentifiers) {\n // take only identifiers that match the definition by type, source and class\n if (!HierarchyNodeIdentifier.isInstanceNodeIdentifier(id)) {\n continue;\n }\n if (id.imodelKey && id.imodelKey !== imodelAccess.imodelKey) {\n continue;\n }\n if (\n id.className !== definition.fullClassName &&\n !(await Promise.all([\n imodelAccess.classDerivesFrom(id.className, definition.fullClassName),\n imodelAccess.classDerivesFrom(definition.fullClassName, id.className),\n ]).then(([isDerivedFrom, isDerivedTo]) => isDerivedFrom || isDerivedTo))\n ) {\n continue;\n }\n const entriesTargetForPathIdentifier = await getEntries(id);\n if (entriesTargetForPathIdentifier) {\n entriesTargetForPathIdentifier.push(id);\n }\n }\n return Array.from(matches.values()).flat();\n }).pipe(\n // only take definitions that have matching path identifiers\n filter((pathIdentifiers) => pathIdentifiers.length > 0),\n\n // for each definition that we're going to use, apply query-level filter\n map((pathIdentifiers) => applyECInstanceIdsFilter(definition, pathIdentifiers)),\n );\n }),\n ),\n ).pipe(toArray()),\n );\n }\n}\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_FilterECInstanceId = \"FilterECInstanceId\";\n\n/** @internal */\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport const ECSQL_COLUMN_NAME_FilterClassName = \"FilterClassName\";\n\nfunction getClassECInstanceIds(filteredInstanceKeys: InstanceKey[]) {\n const classNameECInstanceIds = new Map<string, Id64String[]>();\n for (const key of filteredInstanceKeys) {\n const entry = classNameECInstanceIds.get(key.className);\n if (entry === undefined) {\n classNameECInstanceIds.set(key.className, [key.id]);\n continue;\n }\n entry.push(key.id);\n }\n return classNameECInstanceIds;\n}\n\n/** @internal */\nexport function applyECInstanceIdsFilter(def: InstanceNodesQueryDefinition, filteredInstanceKeys: InstanceKey[]): InstanceNodesQueryDefinition {\n const instanceIdsByClass = getClassECInstanceIds(filteredInstanceKeys);\n return {\n ...def,\n query: {\n ...def.query,\n ctes: [\n ...(def.query.ctes ?? []),\n `FilteringInfo(ECInstanceId, FilterClassName) AS (\n ${Array.from(instanceIdsByClass)\n .map(\n ([className, ecInstanceIds]) => `\n SELECT ECInstanceId, '${className}' AS FilterClassName\n FROM ${className}\n WHERE ECInstanceId IN (${ecInstanceIds.join(\", \")})\n `,\n )\n .join(\" UNION ALL \")}\n )`,\n ],\n ecsql: `\n SELECT\n [q].*,\n IdToHex([f].[ECInstanceId]) AS [${ECSQL_COLUMN_NAME_FilterECInstanceId}],\n [f].[FilterClassName] AS [${ECSQL_COLUMN_NAME_FilterClassName}]\n FROM (\n ${def.query.ecsql}\n ) [q]\n JOIN FilteringInfo [f] ON [f].[ECInstanceId] = [q].[ECInstanceId]\n `,\n },\n };\n}\n\n/** @internal */\nexport function applyECInstanceIdsSelector(def: InstanceNodesQueryDefinition): InstanceNodesQueryDefinition {\n return {\n ...def,\n query: {\n ...def.query,\n ecsql: `\n SELECT\n [q].*,\n IdToHex([q].[ECInstanceId]) AS [${ECSQL_COLUMN_NAME_FilterECInstanceId}],\n [q].[${NodeSelectClauseColumnNames.FullClassName}] AS [${ECSQL_COLUMN_NAME_FilterClassName}]\n FROM (${def.query.ecsql}) [q]\n `,\n },\n };\n}\n"]}
@@ -71,7 +71,9 @@ interface IModelHierarchyProviderProps {
71
71
  * @public
72
72
  */
73
73
  export declare function createIModelHierarchyProvider(props: IModelHierarchyProviderProps): HierarchyProvider & {
74
+ /** @deprecated in 1.4. Use `[Symbol.dispose]` instead. */
74
75
  dispose: () => void;
76
+ [Symbol.dispose]: () => void;
75
77
  };
76
78
  export {};
77
79
  //# sourceMappingURL=IModelHierarchyProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IModelHierarchyProvider.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyProvider.ts"],"names":[],"mappings":"AA2BA,OAAO,EAGL,yBAAyB,EACzB,gBAAgB,EAGhB,KAAK,EAGL,wBAAwB,EAEzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAA0B,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAiBpF,OAAO,EAA6B,mBAAmB,EAA4B,MAAM,gCAAgC,CAAC;AAS1H,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAe7E;;;GAGG;AACH,UAAU,uCAAuC;IAC/C;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,cAAc;AACd,KAAK,YAAY,GAAG,gBAAgB,GAAG,0BAA0B,GAAG,yBAAyB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtH;;;GAGG;AACH,UAAU,4BAA4B;IACpC;;;;;;OAMG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B,wFAAwF;IACxF,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,mBAAmB,EAAE,mBAAmB,CAAC;IAEzC,qGAAqG;IACrG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC,uCAAuC,CAAC,CAAC;IAEpE;;;;OAIG;IACH,SAAS,CAAC,EAAE,wBAAwB,CAAC;IACrC,yCAAyC;IACzC,SAAS,CAAC,EAAE;QACV,2DAA2D;QAC3D,KAAK,EAAE,sBAAsB,EAAE,CAAC;KACjC,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,4BAA4B,GAAG,iBAAiB,GAAG;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CAE9H"}
1
+ {"version":3,"file":"IModelHierarchyProvider.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyProvider.ts"],"names":[],"mappings":"AA2BA,OAAO,EAGL,yBAAyB,EACzB,gBAAgB,EAGhB,KAAK,EAIL,wBAAwB,EAEzB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAGlE,OAAO,EAA0B,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAiBpF,OAAO,EAA6B,mBAAmB,EAA4B,MAAM,gCAAgC,CAAC;AAS1H,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAe7E;;;GAGG;AACH,UAAU,uCAAuC;IAC/C;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;CACf;AAED,cAAc;AACd,KAAK,YAAY,GAAG,gBAAgB,GAAG,0BAA0B,GAAG,yBAAyB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtH;;;GAGG;AACH,UAAU,4BAA4B;IACpC;;;;;;OAMG;IACH,YAAY,EAAE,YAAY,CAAC;IAE3B,wFAAwF;IACxF,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,mBAAmB,EAAE,mBAAmB,CAAC;IAEzC,qGAAqG;IACrG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,OAAO,CAAC,uCAAuC,CAAC,CAAC;IAEpE;;;;OAIG;IACH,SAAS,CAAC,EAAE,wBAAwB,CAAC;IACrC,yCAAyC;IACzC,SAAS,CAAC,EAAE;QACV,2DAA2D;QAC3D,KAAK,EAAE,sBAAsB,EAAE,CAAC;KACjC,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,4BAA4B,GAAG,iBAAiB,GAAG;IACtG,0DAA0D;IAC1D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B,CAEA"}
@@ -41,7 +41,7 @@ export function createIModelHierarchyProvider(props) {
41
41
  }
42
42
  class IModelHierarchyProviderImpl {
43
43
  _imodelAccess;
44
- _imodelChanged;
44
+ _hierarchyChanged;
45
45
  _valuesFormatter;
46
46
  _sourceHierarchyDefinition;
47
47
  _activeHierarchyDefinition;
@@ -52,7 +52,7 @@ class IModelHierarchyProviderImpl {
52
52
  _dispose = new Subject();
53
53
  constructor(props) {
54
54
  this._imodelAccess = props.imodelAccess;
55
- this._imodelChanged = props.imodelChanged ?? new BeEvent();
55
+ this._hierarchyChanged = new BeEvent();
56
56
  this._activeHierarchyDefinition = this._sourceHierarchyDefinition = props.hierarchyDefinition;
57
57
  this._valuesFormatter = props?.formatter ?? createDefaultValueFormatter();
58
58
  this._localizedStrings = { other: "Other", unspecified: "Not specified", ...props?.localizedStrings };
@@ -65,18 +65,23 @@ class IModelHierarchyProviderImpl {
65
65
  size: Math.ceil(queryCacheSize / 2),
66
66
  variationsCount: 1,
67
67
  });
68
- this._unsubscribe = props.imodelChanged?.addListener(() => {
69
- this.invalidateHierarchyCache("Data source changed");
70
- this._dispose.next();
71
- });
72
68
  }
69
+ this._unsubscribe = props.imodelChanged?.addListener(() => {
70
+ this.invalidateHierarchyCache("Data source changed");
71
+ this._dispose.next();
72
+ this._hierarchyChanged.raiseEvent();
73
+ });
73
74
  }
74
- dispose() {
75
+ [Symbol.dispose]() {
75
76
  this._dispose.next();
76
77
  this._unsubscribe?.();
77
78
  }
79
+ /* c8 ignore next 3 */
80
+ dispose() {
81
+ this[Symbol.dispose]();
82
+ }
78
83
  get hierarchyChanged() {
79
- return this._imodelChanged;
84
+ return this._hierarchyChanged;
80
85
  }
81
86
  invalidateHierarchyCache(reason) {
82
87
  doLog({
@@ -91,6 +96,7 @@ class IModelHierarchyProviderImpl {
91
96
  */
92
97
  setFormatter(formatter) {
93
98
  this._valuesFormatter = formatter ?? createDefaultValueFormatter();
99
+ this._hierarchyChanged.raiseEvent({ formatterChange: { newFormatter: this._valuesFormatter } });
94
100
  }
95
101
  setHierarchyFilter(props) {
96
102
  if (!props) {
@@ -98,6 +104,7 @@ class IModelHierarchyProviderImpl {
98
104
  this._activeHierarchyDefinition = this._sourceHierarchyDefinition;
99
105
  this.invalidateHierarchyCache("Hierarchy filter reset");
100
106
  }
107
+ this._hierarchyChanged.raiseEvent({ filterChange: { newFilter: undefined } });
101
108
  return;
102
109
  }
103
110
  this._activeHierarchyDefinition = new FilteringHierarchyDefinition({
@@ -107,6 +114,7 @@ class IModelHierarchyProviderImpl {
107
114
  });
108
115
  this.invalidateHierarchyCache("Hierarchy filter set");
109
116
  this._dispose.next();
117
+ this._hierarchyChanged.raiseEvent({ filterChange: { newFilter: props } });
110
118
  }
111
119
  onGroupingNodeCreated(groupingNode, props) {
112
120
  this._nodesCache?.set({ ...props, parentNode: groupingNode }, { observable: from(groupingNode.children), processingStatus: "pre-processed" });