@itwin/presentation-hierarchies 2.0.0-alpha.0 → 2.0.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +306 -7
- package/README.md +4 -22
- package/lib/cjs/hierarchies/HierarchyMerge.d.ts +19 -0
- package/lib/cjs/hierarchies/HierarchyMerge.d.ts.map +1 -0
- package/lib/cjs/hierarchies/HierarchyMerge.js +43 -0
- package/lib/cjs/hierarchies/HierarchyMerge.js.map +1 -0
- package/lib/cjs/hierarchies/HierarchyNode.d.ts +14 -24
- package/lib/cjs/hierarchies/HierarchyNode.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNode.js +1 -21
- package/lib/cjs/hierarchies/HierarchyNode.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNodeKey.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyNodeKey.js +8 -8
- package/lib/cjs/hierarchies/HierarchyNodeKey.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchyProvider.d.ts +11 -29
- package/lib/cjs/hierarchies/HierarchyProvider.d.ts.map +1 -1
- package/lib/cjs/hierarchies/HierarchyProvider.js +0 -37
- package/lib/cjs/hierarchies/HierarchyProvider.js.map +1 -1
- package/lib/cjs/hierarchies/HierarchySearch.d.ts +167 -0
- package/lib/cjs/hierarchies/HierarchySearch.d.ts.map +1 -0
- package/lib/cjs/hierarchies/HierarchySearch.js +259 -0
- package/lib/cjs/hierarchies/HierarchySearch.js.map +1 -0
- package/lib/cjs/hierarchies/imodel/HierarchyCache.js +3 -3
- package/lib/cjs/hierarchies/imodel/HierarchyCache.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyDefinition.d.ts +15 -4
- package/lib/cjs/hierarchies/imodel/IModelHierarchyDefinition.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyDefinition.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts +46 -11
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js +192 -72
- package/lib/cjs/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.d.ts +2 -2
- package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.js +99 -40
- package/lib/cjs/hierarchies/imodel/NodeSelectQueryFactory.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.d.ts +35 -0
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.d.ts.map +1 -0
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.js +285 -0
- package/lib/cjs/hierarchies/imodel/SearchHierarchyDefinition.js.map +1 -0
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.d.ts +5 -7
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.js +15 -8
- package/lib/cjs/hierarchies/imodel/TreeNodesReader.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/HideIfNoChildren.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/HideIfNoChildren.js +1 -0
- package/lib/cjs/hierarchies/imodel/operators/HideIfNoChildren.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/BaseClassGrouping.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/BaseClassGrouping.js +6 -5
- package/lib/cjs/hierarchies/imodel/operators/grouping/BaseClassGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/ClassGrouping.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/ClassGrouping.js +4 -3
- package/lib/cjs/hierarchies/imodel/operators/grouping/ClassGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/PropertiesGrouping.d.ts.map +1 -1
- package/lib/cjs/hierarchies/imodel/operators/grouping/PropertiesGrouping.js +21 -16
- package/lib/cjs/hierarchies/imodel/operators/grouping/PropertiesGrouping.js.map +1 -1
- package/lib/cjs/hierarchies/internal/Common.d.ts +3 -0
- package/lib/cjs/hierarchies/internal/Common.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/Common.js +12 -1
- package/lib/cjs/hierarchies/internal/Common.js.map +1 -1
- package/lib/cjs/hierarchies/internal/EachValueFrom.d.ts.map +1 -1
- package/lib/cjs/hierarchies/internal/EachValueFrom.js +1 -0
- package/lib/cjs/hierarchies/internal/EachValueFrom.js.map +1 -1
- package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.d.ts +68 -0
- package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.d.ts.map +1 -0
- package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.js +26 -0
- package/lib/cjs/hierarchies/internal/RxjsHierarchyDefinition.js.map +1 -0
- package/lib/cjs/presentation-hierarchies.d.ts +5 -4
- package/lib/cjs/presentation-hierarchies.d.ts.map +1 -1
- package/lib/cjs/presentation-hierarchies.js +7 -7
- package/lib/cjs/presentation-hierarchies.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyMerge.d.ts +19 -0
- package/lib/esm/hierarchies/HierarchyMerge.d.ts.map +1 -0
- package/lib/esm/hierarchies/HierarchyMerge.js +40 -0
- package/lib/esm/hierarchies/HierarchyMerge.js.map +1 -0
- package/lib/esm/hierarchies/HierarchyNode.d.ts +14 -24
- package/lib/esm/hierarchies/HierarchyNode.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyNode.js +0 -20
- package/lib/esm/hierarchies/HierarchyNode.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyNodeKey.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyNodeKey.js +9 -9
- package/lib/esm/hierarchies/HierarchyNodeKey.js.map +1 -1
- package/lib/esm/hierarchies/HierarchyProvider.d.ts +11 -29
- package/lib/esm/hierarchies/HierarchyProvider.d.ts.map +1 -1
- package/lib/esm/hierarchies/HierarchyProvider.js +1 -36
- package/lib/esm/hierarchies/HierarchyProvider.js.map +1 -1
- package/lib/esm/hierarchies/HierarchySearch.d.ts +167 -0
- package/lib/esm/hierarchies/HierarchySearch.d.ts.map +1 -0
- package/lib/esm/hierarchies/HierarchySearch.js +254 -0
- package/lib/esm/hierarchies/HierarchySearch.js.map +1 -0
- package/lib/esm/hierarchies/imodel/HierarchyCache.js +3 -3
- package/lib/esm/hierarchies/imodel/HierarchyCache.js.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyDefinition.d.ts +15 -4
- package/lib/esm/hierarchies/imodel/IModelHierarchyDefinition.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyDefinition.js.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts +46 -11
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js +194 -75
- package/lib/esm/hierarchies/imodel/IModelHierarchyProvider.js.map +1 -1
- package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.d.ts +2 -2
- package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.js +100 -41
- package/lib/esm/hierarchies/imodel/NodeSelectQueryFactory.js.map +1 -1
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.d.ts +35 -0
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.d.ts.map +1 -0
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.js +279 -0
- package/lib/esm/hierarchies/imodel/SearchHierarchyDefinition.js.map +1 -0
- package/lib/esm/hierarchies/imodel/TreeNodesReader.d.ts +5 -7
- package/lib/esm/hierarchies/imodel/TreeNodesReader.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/TreeNodesReader.js +13 -7
- package/lib/esm/hierarchies/imodel/TreeNodesReader.js.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/HideIfNoChildren.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/HideIfNoChildren.js +1 -0
- package/lib/esm/hierarchies/imodel/operators/HideIfNoChildren.js.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/BaseClassGrouping.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/BaseClassGrouping.js +7 -6
- package/lib/esm/hierarchies/imodel/operators/grouping/BaseClassGrouping.js.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/ClassGrouping.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/ClassGrouping.js +5 -4
- package/lib/esm/hierarchies/imodel/operators/grouping/ClassGrouping.js.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/PropertiesGrouping.d.ts.map +1 -1
- package/lib/esm/hierarchies/imodel/operators/grouping/PropertiesGrouping.js +22 -17
- package/lib/esm/hierarchies/imodel/operators/grouping/PropertiesGrouping.js.map +1 -1
- package/lib/esm/hierarchies/internal/Common.d.ts +3 -0
- package/lib/esm/hierarchies/internal/Common.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/Common.js +11 -1
- package/lib/esm/hierarchies/internal/Common.js.map +1 -1
- package/lib/esm/hierarchies/internal/EachValueFrom.d.ts.map +1 -1
- package/lib/esm/hierarchies/internal/EachValueFrom.js +1 -0
- package/lib/esm/hierarchies/internal/EachValueFrom.js.map +1 -1
- package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.d.ts +68 -0
- package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.d.ts.map +1 -0
- package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.js +23 -0
- package/lib/esm/hierarchies/internal/RxjsHierarchyDefinition.js.map +1 -0
- package/lib/esm/presentation-hierarchies.d.ts +5 -4
- package/lib/esm/presentation-hierarchies.d.ts.map +1 -1
- package/lib/esm/presentation-hierarchies.js +3 -3
- package/lib/esm/presentation-hierarchies.js.map +1 -1
- package/package.json +19 -19
- package/lib/cjs/hierarchies/HierarchyFiltering.d.ts +0 -110
- package/lib/cjs/hierarchies/HierarchyFiltering.d.ts.map +0 -1
- package/lib/cjs/hierarchies/HierarchyFiltering.js +0 -210
- package/lib/cjs/hierarchies/HierarchyFiltering.js.map +0 -1
- package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.d.ts +0 -34
- package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +0 -1
- package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.js +0 -270
- package/lib/cjs/hierarchies/imodel/FilteringHierarchyDefinition.js.map +0 -1
- package/lib/esm/hierarchies/HierarchyFiltering.d.ts +0 -110
- package/lib/esm/hierarchies/HierarchyFiltering.d.ts.map +0 -1
- package/lib/esm/hierarchies/HierarchyFiltering.js +0 -205
- package/lib/esm/hierarchies/HierarchyFiltering.js.map +0 -1
- package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.d.ts +0 -34
- package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.d.ts.map +0 -1
- package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.js +0 -264
- package/lib/esm/hierarchies/imodel/FilteringHierarchyDefinition.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "../internal/DisposePolyfill.js";
|
|
2
2
|
import { ECClassHierarchyInspector, ECSchemaProvider, Event, IPrimitiveValueFormatter } from "@itwin/presentation-shared";
|
|
3
|
-
import { HierarchyFilteringPath } from "../HierarchyFiltering.js";
|
|
4
3
|
import { HierarchyProvider } from "../HierarchyProvider.js";
|
|
4
|
+
import { HierarchySearchPath } from "../HierarchySearch.js";
|
|
5
5
|
import { HierarchyDefinition } from "./IModelHierarchyDefinition.js";
|
|
6
6
|
import { LimitingECSqlQueryExecutor } from "./LimitingECSqlQueryExecutor.js";
|
|
7
7
|
/**
|
|
@@ -37,7 +37,10 @@ interface IModelHierarchyProviderProps {
|
|
|
37
37
|
* @see `ECClassHierarchyInspector`
|
|
38
38
|
*/
|
|
39
39
|
imodelAccess: IModelAccess;
|
|
40
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* An event that is raised when iModel data, that may affect the hierarchy, changes. The created provider
|
|
42
|
+
* subscribes to the event to know that it needs to reload the data, and unsubscribes on disposal.
|
|
43
|
+
*/
|
|
41
44
|
imodelChanged?: Event<() => void>;
|
|
42
45
|
/**
|
|
43
46
|
* A function that returns a hierarchy definition, describing how the hierarchy that the provider should be create. The
|
|
@@ -59,22 +62,54 @@ interface IModelHierarchyProviderProps {
|
|
|
59
62
|
* by calling `setFormatter` on the provider instance.
|
|
60
63
|
*/
|
|
61
64
|
formatter?: IPrimitiveValueFormatter;
|
|
62
|
-
/** Props for
|
|
63
|
-
|
|
65
|
+
/** Props for search the hierarchy. */
|
|
66
|
+
search?: {
|
|
64
67
|
/** A list of node identifiers from root to target node. */
|
|
65
|
-
paths:
|
|
68
|
+
paths: HierarchySearchPath[];
|
|
66
69
|
};
|
|
67
70
|
}
|
|
68
71
|
/**
|
|
69
|
-
* Creates an instance of `HierarchyProvider` that creates a hierarchy based on given iModel and
|
|
72
|
+
* Creates an instance of `HierarchyProvider` that creates a hierarchy based on given the iModel and
|
|
70
73
|
* a hierarchy definition, which defines each hierarchy level through ECSQL queries.
|
|
71
74
|
*
|
|
72
75
|
* @public
|
|
73
76
|
*/
|
|
74
|
-
export declare function createIModelHierarchyProvider(props: IModelHierarchyProviderProps): HierarchyProvider &
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
export declare function createIModelHierarchyProvider(props: IModelHierarchyProviderProps): HierarchyProvider & Disposable;
|
|
78
|
+
/**
|
|
79
|
+
* Props for `createMergedIModelHierarchyProvider`.
|
|
80
|
+
* @alpha
|
|
81
|
+
*/
|
|
82
|
+
interface MergedIModelHierarchyProviderProps extends Omit<IModelHierarchyProviderProps, "imodelAccess" | "imodelChanged"> {
|
|
83
|
+
/**
|
|
84
|
+
* A list of iModels to create merged hierarchy for.
|
|
85
|
+
*
|
|
86
|
+
* **Warning:** These **must** all be different versions of the same iModel, ordered from the earliest to the
|
|
87
|
+
* latest version. Not obeying this rule may result in undefined behavior.
|
|
88
|
+
*/
|
|
89
|
+
imodels: Array<{
|
|
90
|
+
/**
|
|
91
|
+
* An object that provides access to iModel's data and metadata.
|
|
92
|
+
*
|
|
93
|
+
* @see `ECSchemaProvider`
|
|
94
|
+
* @see `LimitingECSqlQueryExecutor`
|
|
95
|
+
* @see `ECClassHierarchyInspector`
|
|
96
|
+
*/
|
|
97
|
+
imodelAccess: IModelAccess;
|
|
98
|
+
/**
|
|
99
|
+
* An event that is raised when iModel data, that may affect the hierarchy, changes. The created provider
|
|
100
|
+
* subscribes to the event to know that it needs to reload the data, and unsubscribes on disposal.
|
|
101
|
+
*/
|
|
102
|
+
imodelChanged?: Event<() => void>;
|
|
103
|
+
}>;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Creates an instance of `HierarchyProvider` that creates a hierarchy based on multiple version of **the same** iModel
|
|
107
|
+
* and a hierarchy definition, which defines each hierarchy level through ECSQL queries.
|
|
108
|
+
*
|
|
109
|
+
* **Warning:** This is an experimental API that **should not be used in production**.
|
|
110
|
+
*
|
|
111
|
+
* @alpha
|
|
112
|
+
*/
|
|
113
|
+
export declare function createMergedIModelHierarchyProvider(props: MergedIModelHierarchyProviderProps): HierarchyProvider & Disposable;
|
|
79
114
|
export {};
|
|
80
115
|
//# sourceMappingURL=IModelHierarchyProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IModelHierarchyProvider.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyProvider.ts"],"names":[],"mappings":"AAKA,OAAO,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"IModelHierarchyProvider.d.ts","sourceRoot":"","sources":["../../../../src/hierarchies/imodel/IModelHierarchyProvider.ts"],"names":[],"mappings":"AAKA,OAAO,gCAAgC,CAAC;AA4BxC,OAAO,EAGL,yBAAyB,EACzB,gBAAgB,EAGhB,KAAK,EAIL,wBAAwB,EAEzB,MAAM,4BAA4B,CAAC;AAIpC,OAAO,EAA0B,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACpF,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAiB5D,OAAO,EAGL,mBAAmB,EAGpB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAgB7E;;;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;;;OAGG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IAElC;;;OAGG;IACH,mBAAmB,EAAE,mBAAmB,CAAC;IAEzC,qGAAqG;IACrG,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B;;;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;IAErC,sCAAsC;IACtC,MAAM,CAAC,EAAE;QACP,2DAA2D;QAC3D,KAAK,EAAE,mBAAmB,EAAE,CAAC;KAC9B,CAAC;CACH;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,4BAA4B,GAAG,iBAAiB,GAAG,UAAU,CAGjH;AAED;;;GAGG;AACH,UAAU,kCAAmC,SAAQ,IAAI,CAAC,4BAA4B,EAAE,cAAc,GAAG,eAAe,CAAC;IACvH;;;;;OAKG;IACH,OAAO,EAAE,KAAK,CAAC;QACb;;;;;;WAMG;QACH,YAAY,EAAE,YAAY,CAAC;QAE3B;;;WAGG;QACH,aAAa,CAAC,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;KACnC,CAAC,CAAC;CACJ;AAED;;;;;;;GAOG;AACH,wBAAgB,mCAAmC,CAAC,KAAK,EAAE,kCAAkC,GAAG,iBAAiB,GAAG,UAAU,CAE7H"}
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import "../internal/DisposePolyfill.js";
|
|
6
|
-
import { catchError, concat, defaultIfEmpty, defer, EMPTY, filter, finalize, from, map, merge, mergeAll, mergeMap, of, Subject, take, takeUntil, tap, } from "rxjs";
|
|
6
|
+
import { catchError, concat, defaultIfEmpty, defer, EMPTY, filter, finalize, from, fromEventPattern, identity, map, merge, mergeAll, mergeMap, of, reduce, Subject, take, takeUntil, tap, } from "rxjs";
|
|
7
7
|
import { assert, BeEvent, Guid, StopWatch } from "@itwin/core-bentley";
|
|
8
|
-
import { createDefaultValueFormatter, formatConcatenatedValue, normalizeFullClassName, } from "@itwin/presentation-shared";
|
|
8
|
+
import { createDefaultValueFormatter, formatConcatenatedValue, InstanceKey, normalizeFullClassName, } from "@itwin/presentation-shared";
|
|
9
9
|
import { RowsLimitExceededError } from "../HierarchyErrors.js";
|
|
10
10
|
import { HierarchyNode } from "../HierarchyNode.js";
|
|
11
11
|
import { HierarchyNodeKey } from "../HierarchyNodeKey.js";
|
|
12
|
+
import { HierarchySearchPath } from "../HierarchySearch.js";
|
|
12
13
|
import { LOGGING_NAMESPACE as BASE_LOGGING_NAMESPACE, LOGGING_NAMESPACE_INTERNAL as BASE_LOGGING_NAMESPACE_INTERNAL, LOGGING_NAMESPACE_PERFORMANCE as BASE_LOGGING_NAMESPACE_PERFORMANCE, createNodeIdentifierForLogging, hasChildren, } from "../internal/Common.js";
|
|
13
14
|
import { eachValueFrom } from "../internal/EachValueFrom.js";
|
|
14
15
|
import { doLog, log } from "../internal/LoggingUtils.js";
|
|
@@ -16,15 +17,16 @@ import { partition } from "../internal/operators/Partition.js";
|
|
|
16
17
|
import { reduceToMergeMapList } from "../internal/operators/ReduceToMergeMap.js";
|
|
17
18
|
import { shareReplayWithErrors } from "../internal/operators/ShareReplayWithErrors.js";
|
|
18
19
|
import { sortNodesByLabelOperator } from "../internal/operators/Sorting.js";
|
|
20
|
+
import { getRxjsHierarchyDefinition } from "../internal/RxjsHierarchyDefinition.js";
|
|
19
21
|
import { SubscriptionScheduler } from "../internal/SubscriptionScheduler.js";
|
|
20
|
-
import { FilteringHierarchyDefinition } from "./FilteringHierarchyDefinition.js";
|
|
21
22
|
import { HierarchyCache } from "./HierarchyCache.js";
|
|
22
|
-
import { HierarchyNodesDefinition } from "./IModelHierarchyDefinition.js";
|
|
23
|
+
import { HierarchyNodesDefinition, } from "./IModelHierarchyDefinition.js";
|
|
23
24
|
import { NodeSelectClauseColumnNames } from "./NodeSelectQueryFactory.js";
|
|
24
25
|
import { createDetermineChildrenOperator } from "./operators/DetermineChildren.js";
|
|
25
26
|
import { createGroupingOperator } from "./operators/Grouping.js";
|
|
26
27
|
import { createHideIfNoChildrenOperator } from "./operators/HideIfNoChildren.js";
|
|
27
28
|
import { createHideNodesInHierarchyOperator } from "./operators/HideNodesInHierarchy.js";
|
|
29
|
+
import { SearchHierarchyDefinition } from "./SearchHierarchyDefinition.js";
|
|
28
30
|
import { readNodes } from "./TreeNodesReader.js";
|
|
29
31
|
const LOGGING_NAMESPACE = `${BASE_LOGGING_NAMESPACE}.IModelHierarchyProvider`;
|
|
30
32
|
const LOGGING_NAMESPACE_INTERNAL = `${BASE_LOGGING_NAMESPACE_INTERNAL}.IModelHierarchyProvider`;
|
|
@@ -32,33 +34,57 @@ const LOGGING_NAMESPACE_PERFORMANCE = `${BASE_LOGGING_NAMESPACE_PERFORMANCE}.IMo
|
|
|
32
34
|
const DEFAULT_QUERY_CONCURRENCY = 10;
|
|
33
35
|
const DEFAULT_QUERY_CACHE_SIZE = 1;
|
|
34
36
|
/**
|
|
35
|
-
* Creates an instance of `HierarchyProvider` that creates a hierarchy based on given iModel and
|
|
37
|
+
* Creates an instance of `HierarchyProvider` that creates a hierarchy based on given the iModel and
|
|
36
38
|
* a hierarchy definition, which defines each hierarchy level through ECSQL queries.
|
|
37
39
|
*
|
|
38
40
|
* @public
|
|
39
41
|
*/
|
|
40
42
|
export function createIModelHierarchyProvider(props) {
|
|
43
|
+
const { imodelAccess, imodelChanged, ...restProps } = props;
|
|
44
|
+
return createMergedIModelHierarchyProvider({ ...restProps, imodels: [{ imodelAccess, imodelChanged }] });
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Creates an instance of `HierarchyProvider` that creates a hierarchy based on multiple version of **the same** iModel
|
|
48
|
+
* and a hierarchy definition, which defines each hierarchy level through ECSQL queries.
|
|
49
|
+
*
|
|
50
|
+
* **Warning:** This is an experimental API that **should not be used in production**.
|
|
51
|
+
*
|
|
52
|
+
* @alpha
|
|
53
|
+
*/
|
|
54
|
+
export function createMergedIModelHierarchyProvider(props) {
|
|
41
55
|
return new IModelHierarchyProviderImpl(props);
|
|
42
56
|
}
|
|
43
57
|
class IModelHierarchyProviderImpl {
|
|
44
|
-
|
|
58
|
+
_imodels;
|
|
45
59
|
_hierarchyChanged;
|
|
46
60
|
_valuesFormatter;
|
|
47
61
|
_sourceHierarchyDefinition;
|
|
48
62
|
_activeHierarchyDefinition;
|
|
49
63
|
_localizedStrings;
|
|
50
|
-
|
|
64
|
+
_queryConcurrency;
|
|
65
|
+
_querySchedulers;
|
|
51
66
|
_nodesCache;
|
|
52
67
|
_unsubscribe;
|
|
53
68
|
_dispose = new Subject();
|
|
69
|
+
#componentId;
|
|
70
|
+
#componentName;
|
|
71
|
+
#sourceName;
|
|
54
72
|
constructor(props) {
|
|
55
|
-
|
|
73
|
+
if (props.imodels.length === 0) {
|
|
74
|
+
throw new Error(`Creating an iModel hierarchy provider requires at least one iModel.`);
|
|
75
|
+
}
|
|
76
|
+
this.#componentId = Guid.createValue();
|
|
77
|
+
this.#componentName = "IModelHierarchyProviderImpl";
|
|
78
|
+
/* c8 ignore next */
|
|
79
|
+
this.#sourceName = props.sourceName ?? `${this.#componentName}:${this.#componentId}`;
|
|
80
|
+
this._imodels = props.imodels;
|
|
56
81
|
this._hierarchyChanged = new BeEvent();
|
|
57
|
-
this._activeHierarchyDefinition = this._sourceHierarchyDefinition = props.hierarchyDefinition;
|
|
82
|
+
this._activeHierarchyDefinition = this._sourceHierarchyDefinition = getRxjsHierarchyDefinition(props.hierarchyDefinition);
|
|
58
83
|
this._valuesFormatter = props?.formatter ?? createDefaultValueFormatter();
|
|
59
84
|
this._localizedStrings = { other: "Other", unspecified: "Not specified", ...props?.localizedStrings };
|
|
60
|
-
this.
|
|
61
|
-
this.
|
|
85
|
+
this._queryConcurrency = props.queryConcurrency ?? DEFAULT_QUERY_CONCURRENCY;
|
|
86
|
+
this._querySchedulers = new Map();
|
|
87
|
+
this.setHierarchySearch(props.search);
|
|
62
88
|
const queryCacheSize = props.queryCacheSize ?? DEFAULT_QUERY_CACHE_SIZE;
|
|
63
89
|
if (queryCacheSize !== 0) {
|
|
64
90
|
this._nodesCache = new HierarchyCache({
|
|
@@ -67,11 +93,18 @@ class IModelHierarchyProviderImpl {
|
|
|
67
93
|
variationsCount: 1,
|
|
68
94
|
});
|
|
69
95
|
}
|
|
70
|
-
|
|
71
|
-
|
|
96
|
+
const imodelChangeSubscription = from(this._imodels)
|
|
97
|
+
.pipe(mergeMap(({ imodelAccess, imodelChanged }) => imodelChanged
|
|
98
|
+
? fromEventPattern((handler) => imodelChanged.addListener(handler), (handler) => imodelChanged.removeListener(handler), () => imodelAccess)
|
|
99
|
+
: EMPTY))
|
|
100
|
+
.subscribe(({ imodelKey }) => {
|
|
101
|
+
this.invalidateHierarchyCache(`Data source changed: "${imodelKey}"`);
|
|
72
102
|
this._dispose.next();
|
|
73
103
|
this._hierarchyChanged.raiseEvent();
|
|
74
104
|
});
|
|
105
|
+
this._unsubscribe = () => {
|
|
106
|
+
imodelChangeSubscription.unsubscribe();
|
|
107
|
+
};
|
|
75
108
|
}
|
|
76
109
|
[Symbol.dispose]() {
|
|
77
110
|
this._dispose.next();
|
|
@@ -84,6 +117,17 @@ class IModelHierarchyProviderImpl {
|
|
|
84
117
|
get hierarchyChanged() {
|
|
85
118
|
return this._hierarchyChanged;
|
|
86
119
|
}
|
|
120
|
+
getQueryScheduler(imodelKey) {
|
|
121
|
+
let scheduler = this._querySchedulers.get(imodelKey);
|
|
122
|
+
if (!scheduler) {
|
|
123
|
+
scheduler = new SubscriptionScheduler(this._queryConcurrency);
|
|
124
|
+
this._querySchedulers.set(imodelKey, scheduler);
|
|
125
|
+
}
|
|
126
|
+
return scheduler;
|
|
127
|
+
}
|
|
128
|
+
getPrimaryIModelAccess() {
|
|
129
|
+
return this._imodels[this._imodels.length - 1].imodelAccess;
|
|
130
|
+
}
|
|
87
131
|
invalidateHierarchyCache(reason) {
|
|
88
132
|
doLog({
|
|
89
133
|
category: `${LOGGING_NAMESPACE}.Events`,
|
|
@@ -99,23 +143,24 @@ class IModelHierarchyProviderImpl {
|
|
|
99
143
|
this._valuesFormatter = formatter ?? createDefaultValueFormatter();
|
|
100
144
|
this._hierarchyChanged.raiseEvent({ formatterChange: { newFormatter: this._valuesFormatter } });
|
|
101
145
|
}
|
|
102
|
-
|
|
146
|
+
setHierarchySearch(props) {
|
|
103
147
|
if (!props) {
|
|
104
148
|
if (this._sourceHierarchyDefinition !== this._activeHierarchyDefinition) {
|
|
105
149
|
this._activeHierarchyDefinition = this._sourceHierarchyDefinition;
|
|
106
|
-
this.invalidateHierarchyCache("Hierarchy
|
|
150
|
+
this.invalidateHierarchyCache("Hierarchy search reset");
|
|
107
151
|
}
|
|
108
|
-
this._hierarchyChanged.raiseEvent({
|
|
152
|
+
this._hierarchyChanged.raiseEvent({ searchChange: { newSearch: undefined } });
|
|
109
153
|
return;
|
|
110
154
|
}
|
|
111
|
-
this._activeHierarchyDefinition = new
|
|
112
|
-
imodelAccess: this.
|
|
155
|
+
this._activeHierarchyDefinition = new SearchHierarchyDefinition({
|
|
156
|
+
imodelAccess: this.getPrimaryIModelAccess(),
|
|
113
157
|
source: this._sourceHierarchyDefinition,
|
|
114
|
-
|
|
158
|
+
sourceName: this.#sourceName,
|
|
159
|
+
targetPaths: props.paths,
|
|
115
160
|
});
|
|
116
|
-
this.invalidateHierarchyCache("Hierarchy
|
|
161
|
+
this.invalidateHierarchyCache("Hierarchy search set");
|
|
117
162
|
this._dispose.next();
|
|
118
|
-
this._hierarchyChanged.raiseEvent({
|
|
163
|
+
this._hierarchyChanged.raiseEvent({ searchChange: { newSearch: props } });
|
|
119
164
|
}
|
|
120
165
|
onGroupingNodeCreated(groupingNode, props) {
|
|
121
166
|
this._nodesCache?.set({ ...props, parentNode: groupingNode }, { observable: from(groupingNode.children), processingStatus: "pre-processed" });
|
|
@@ -126,48 +171,53 @@ class IModelHierarchyProviderImpl {
|
|
|
126
171
|
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
127
172
|
message: /* c8 ignore next */ () => `[${requestContext.requestId}] Requesting hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
128
173
|
});
|
|
129
|
-
return from(
|
|
174
|
+
return from(this._imodels).pipe(mergeMap(({ imodelAccess }, imodelAccessIndex) => {
|
|
130
175
|
let parentNode = props.parentNode;
|
|
131
|
-
if (parentNode && HierarchyNode.isGeneric(parentNode) && parentNode.key.source && parentNode.key.source !== this
|
|
132
|
-
return
|
|
176
|
+
if (parentNode && HierarchyNode.isGeneric(parentNode) && parentNode.key.source && parentNode.key.source !== this.#sourceName) {
|
|
177
|
+
return EMPTY;
|
|
133
178
|
}
|
|
134
179
|
if (parentNode && HierarchyNode.isInstancesNode(parentNode)) {
|
|
135
180
|
parentNode = {
|
|
136
181
|
...parentNode,
|
|
137
182
|
key: {
|
|
138
183
|
...parentNode.key,
|
|
139
|
-
instanceKeys: parentNode.key.instanceKeys.filter((ik) => !ik.imodelKey || ik.imodelKey ===
|
|
184
|
+
instanceKeys: parentNode.key.instanceKeys.filter((ik) => !ik.imodelKey || ik.imodelKey === imodelAccess.imodelKey),
|
|
140
185
|
},
|
|
141
186
|
};
|
|
142
187
|
assert(HierarchyNodeKey.isInstances(parentNode.key));
|
|
143
188
|
if (parentNode.key.instanceKeys.length === 0) {
|
|
144
|
-
return
|
|
189
|
+
return EMPTY;
|
|
145
190
|
}
|
|
146
191
|
}
|
|
147
|
-
return this._activeHierarchyDefinition.defineHierarchyLevel({ ...defineHierarchyLevelProps, parentNode })
|
|
148
|
-
|
|
192
|
+
return this._activeHierarchyDefinition.defineHierarchyLevel({ ...defineHierarchyLevelProps, parentNode, imodelAccess }).pipe(mergeAll(), map(
|
|
193
|
+
/* Using `as` to work around TS not understanding that `{ x: A, y: B | C }` is the same as `{ x: A } & ({ y: B } | { y: C })` */
|
|
194
|
+
(hierarchyNodesDefinition) => ({ imodelAccess, imodelAccessIndex, hierarchyNodesDefinition })));
|
|
195
|
+
}), finalize(() => doLog({
|
|
149
196
|
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
150
197
|
message: /* c8 ignore next */ () => `[${requestContext.requestId}] Received all hierarchy level definitions for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
151
198
|
})));
|
|
152
199
|
}
|
|
153
200
|
createSourceNodesObservable(props) {
|
|
154
201
|
// pipe definitions to nodes and put "share replay" on it
|
|
155
|
-
return this.createHierarchyLevelDefinitionsObservable(props).pipe(mergeMap((def) => {
|
|
202
|
+
return this.createHierarchyLevelDefinitionsObservable(props).pipe(mergeMap(({ imodelAccess, imodelAccessIndex, hierarchyNodesDefinition: def }) => defer(() => {
|
|
156
203
|
if (HierarchyNodesDefinition.isGenericNode(def)) {
|
|
157
|
-
return of({
|
|
204
|
+
return of({
|
|
205
|
+
...def.node,
|
|
206
|
+
key: { type: "generic", id: def.node.key, source: this.#sourceName },
|
|
207
|
+
});
|
|
158
208
|
}
|
|
159
|
-
return this.
|
|
160
|
-
queryExecutor:
|
|
209
|
+
return this.getQueryScheduler(imodelAccess.imodelKey).scheduleSubscription(of(def.query).pipe(map((query) => createInstanceKeysFilteredQuery(query, props.targetInstanceKeys)), mergeMap((query) => readNodes({
|
|
210
|
+
queryExecutor: imodelAccess,
|
|
161
211
|
query,
|
|
162
212
|
limit: props.hierarchyLevelSizeLimit,
|
|
163
213
|
parser: this._activeHierarchyDefinition.parseNode
|
|
164
|
-
?
|
|
214
|
+
? ({ row }) => this._activeHierarchyDefinition.parseNode({ row, parentNode: props.parentNode, imodelKey: imodelAccess.imodelKey })
|
|
165
215
|
: undefined,
|
|
166
216
|
})), map((node) => ({
|
|
167
217
|
...node,
|
|
168
|
-
key: { ...node.key, instanceKeys: node.key.instanceKeys.map((key) => ({ ...key, imodelKey:
|
|
218
|
+
key: { ...node.key, instanceKeys: node.key.instanceKeys.map((key) => ({ ...key, imodelKey: imodelAccess.imodelKey })) },
|
|
169
219
|
}))));
|
|
170
|
-
}), finalize(() => doLog({
|
|
220
|
+
}).pipe(map((node) => ({ imodelAccess, imodelAccessIndex, node })))), mergeNodes, map(({ node }) => node), finalize(() => doLog({
|
|
171
221
|
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
172
222
|
message: /* c8 ignore next */ () => `[${props.requestContext.requestId}] Read all child nodes ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
173
223
|
})), shareReplayWithErrors());
|
|
@@ -179,8 +229,9 @@ class IModelHierarchyProviderImpl {
|
|
|
179
229
|
// set parent node keys on the source node
|
|
180
230
|
map((node) => Object.assign(node, { parentKeys: createParentNodeKeysList(props.parentNode) })),
|
|
181
231
|
// format `ConcatenatedValue` labels into string labels
|
|
182
|
-
mergeMap(
|
|
232
|
+
mergeMap((node) => applyLabelsFormatting(node, this._valuesFormatter)),
|
|
183
233
|
// we have `ProcessedHierarchyNode` from here
|
|
234
|
+
// let consumers step-in
|
|
184
235
|
preProcessNodes(this._activeHierarchyDefinition),
|
|
185
236
|
// process hiding
|
|
186
237
|
createHideIfNoChildrenOperator((n) => this.getChildNodesObservables({ parentNode: n, requestContext: props.requestContext }).hasNodes), createHideNodesInHierarchyOperator(
|
|
@@ -191,7 +242,7 @@ class IModelHierarchyProviderImpl {
|
|
|
191
242
|
})));
|
|
192
243
|
}
|
|
193
244
|
createProcessedNodesObservable(preprocessedNodesObservable, props) {
|
|
194
|
-
return preprocessedNodesObservable.pipe(createGroupingOperator(this.
|
|
245
|
+
return preprocessedNodesObservable.pipe(createGroupingOperator(this.getPrimaryIModelAccess(), props.parentNode, this._valuesFormatter, this._localizedStrings, undefined, (gn) => this.onGroupingNodeCreated(gn, props)), finalize(() => doLog({
|
|
195
246
|
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
196
247
|
message: /* c8 ignore next */ () => `[${props.requestContext.requestId}] Finished grouping child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
197
248
|
})));
|
|
@@ -201,9 +252,7 @@ class IModelHierarchyProviderImpl {
|
|
|
201
252
|
if ("processingParams" in n) {
|
|
202
253
|
delete n.processingParams;
|
|
203
254
|
}
|
|
204
|
-
return
|
|
205
|
-
children: hasChildren(n),
|
|
206
|
-
});
|
|
255
|
+
return { ...n, children: hasChildren(n) };
|
|
207
256
|
}), takeUntil(this._dispose), finalize(() => doLog({
|
|
208
257
|
category: LOGGING_NAMESPACE_PERFORMANCE,
|
|
209
258
|
message: /* c8 ignore next */ () => `[${props.requestContext.requestId}] Finished finalizing child nodes for ${createNodeIdentifierForLogging(props.parentNode)}`,
|
|
@@ -237,13 +286,13 @@ class IModelHierarchyProviderImpl {
|
|
|
237
286
|
return cached;
|
|
238
287
|
}
|
|
239
288
|
// if we don't find an entry for a grouping node, we load its instances by getting a query and applying
|
|
240
|
-
// a
|
|
241
|
-
let
|
|
289
|
+
// a search based on grouped instance keys
|
|
290
|
+
let targetInstanceKeys;
|
|
242
291
|
let parentNonGroupingNode;
|
|
243
292
|
if (parentNode) {
|
|
244
293
|
if (HierarchyNode.isGroupingNode(parentNode)) {
|
|
245
294
|
parentNonGroupingNode = parentNode.nonGroupingAncestor;
|
|
246
|
-
|
|
295
|
+
targetInstanceKeys = parentNode.groupedInstanceKeys;
|
|
247
296
|
}
|
|
248
297
|
else {
|
|
249
298
|
// not sure why type checker doesn't pick this up
|
|
@@ -254,7 +303,7 @@ class IModelHierarchyProviderImpl {
|
|
|
254
303
|
const nonGroupingNodeChildrenRequestProps = {
|
|
255
304
|
...restProps,
|
|
256
305
|
parentNode: parentNonGroupingNode,
|
|
257
|
-
...(
|
|
306
|
+
...(targetInstanceKeys ? { targetInstanceKeys } : undefined),
|
|
258
307
|
};
|
|
259
308
|
const value = { observable: this.createSourceNodesObservable(nonGroupingNodeChildrenRequestProps), processingStatus: "none" };
|
|
260
309
|
this._nodesCache?.set(nonGroupingNodeChildrenRequestProps, value);
|
|
@@ -318,11 +367,11 @@ class IModelHierarchyProviderImpl {
|
|
|
318
367
|
return from(parentNode.groupedInstanceKeys);
|
|
319
368
|
}
|
|
320
369
|
assert(!parentNode || HierarchyNode.isGeneric(parentNode) || HierarchyNode.isInstancesNode(parentNode));
|
|
321
|
-
const hierarchyLevelDefinitions = this.createHierarchyLevelDefinitionsObservable({ parentNode, instanceFilter, requestContext });
|
|
322
370
|
// split the definitions based on whether they're for generic nodes or for instance nodes
|
|
323
|
-
const
|
|
371
|
+
const hierarchyLevelDefinitions = this.createHierarchyLevelDefinitionsObservable({ parentNode, instanceFilter, requestContext });
|
|
372
|
+
const [instanceDefs, genericDefs] = partition(hierarchyLevelDefinitions, (x) => HierarchyNodesDefinition.isInstanceNodesQuery(x.hierarchyNodesDefinition));
|
|
324
373
|
// query instance keys and a flag whether they should be hidden
|
|
325
|
-
const instanceKeys = instanceDefs.pipe(mergeMap((def) => this.
|
|
374
|
+
const instanceKeys = instanceDefs.pipe(mergeMap(({ imodelAccess, hierarchyNodesDefinition: def }) => this.getQueryScheduler(imodelAccess.imodelKey).scheduleSubscription(of(def.query).pipe(mergeMap(async (query) => {
|
|
326
375
|
const ecsql = `
|
|
327
376
|
SELECT
|
|
328
377
|
${NodeSelectClauseColumnNames.FullClassName},
|
|
@@ -332,12 +381,16 @@ class IModelHierarchyProviderImpl {
|
|
|
332
381
|
${query.ecsql}
|
|
333
382
|
)
|
|
334
383
|
`;
|
|
335
|
-
const reader =
|
|
384
|
+
const reader = imodelAccess.createQueryReader({ ...query, ecsql }, {
|
|
385
|
+
rowFormat: "Indexes",
|
|
386
|
+
limit: hierarchyLevelSizeLimit,
|
|
387
|
+
restartToken: `${this.#componentName}/${this.#componentId}/node-instance-keys/${Guid.createValue()}`,
|
|
388
|
+
});
|
|
336
389
|
return from(reader).pipe(map((row) => ({
|
|
337
390
|
key: {
|
|
338
391
|
className: normalizeFullClassName(row[0]),
|
|
339
392
|
id: row[1],
|
|
340
|
-
imodelKey:
|
|
393
|
+
imodelKey: imodelAccess.imodelKey,
|
|
341
394
|
},
|
|
342
395
|
hide: !!row[2],
|
|
343
396
|
})));
|
|
@@ -347,17 +400,17 @@ class IModelHierarchyProviderImpl {
|
|
|
347
400
|
// hidden items' handling:
|
|
348
401
|
// - if a generic node is hidden, we'll want to retrieve instance keys of its children, otherwise we don't care about it,
|
|
349
402
|
// - if an instance key is hidden, we want to create a merged node similar to what we do in `createHideNodesInHierarchyOperator`
|
|
350
|
-
const hiddenParentNodes = merge(genericDefs.pipe(filter((
|
|
403
|
+
const hiddenParentNodes = merge(genericDefs.pipe(filter(({ hierarchyNodesDefinition }) => !!hierarchyNodesDefinition.node.processingParams?.hideInHierarchy), map(({ hierarchyNodesDefinition }) => ({
|
|
351
404
|
type: "generic",
|
|
352
|
-
id:
|
|
353
|
-
source: this
|
|
405
|
+
id: hierarchyNodesDefinition.node.key,
|
|
406
|
+
source: this.#sourceName,
|
|
354
407
|
}))), hiddenNodeInstanceKeys.pipe(
|
|
355
408
|
// first merge all keys by class
|
|
356
|
-
reduceToMergeMapList(({ key }) => key.className, ({ key }) => key
|
|
409
|
+
reduceToMergeMapList(({ key }) => key.className, ({ key }) => key),
|
|
357
410
|
// then, for each class, create an instance key
|
|
358
|
-
mergeMap((mergedMap) => [...mergedMap.entries()].map(([className,
|
|
411
|
+
mergeMap((mergedMap) => [...mergedMap.entries()].map(([className, keys]) => ({
|
|
359
412
|
type: "instances",
|
|
360
|
-
instanceKeys:
|
|
413
|
+
instanceKeys: keys.map(({ id, imodelKey }) => ({ className, id, imodelKey })),
|
|
361
414
|
}))))).pipe(map((key) => ({
|
|
362
415
|
key,
|
|
363
416
|
parentKeys: [],
|
|
@@ -395,26 +448,22 @@ class IModelHierarchyProviderImpl {
|
|
|
395
448
|
}
|
|
396
449
|
}
|
|
397
450
|
function preProcessNodes(hierarchyFactory) {
|
|
398
|
-
return hierarchyFactory.preProcessNode
|
|
399
|
-
? processNodes(hierarchyFactory.preProcessNode.bind(hierarchyFactory))
|
|
400
|
-
: (o) => o;
|
|
451
|
+
return hierarchyFactory.preProcessNode ? processNodes(hierarchyFactory.preProcessNode) : identity;
|
|
401
452
|
}
|
|
402
453
|
function postProcessNodes(hierarchyFactory) {
|
|
403
|
-
return hierarchyFactory.postProcessNode
|
|
404
|
-
? processNodes(hierarchyFactory.postProcessNode.bind(hierarchyFactory))
|
|
405
|
-
: (o) => o;
|
|
454
|
+
return hierarchyFactory.postProcessNode ? processNodes(hierarchyFactory.postProcessNode) : identity;
|
|
406
455
|
}
|
|
407
456
|
function processNodes(processor) {
|
|
408
|
-
return (nodes) => nodes.pipe(mergeMap(processor)
|
|
457
|
+
return (nodes) => nodes.pipe(mergeMap(processor));
|
|
409
458
|
}
|
|
410
|
-
|
|
411
|
-
return {
|
|
459
|
+
function applyLabelsFormatting(node, valueFormatter) {
|
|
460
|
+
return from(formatConcatenatedValue({
|
|
461
|
+
value: node.label,
|
|
462
|
+
valueFormatter,
|
|
463
|
+
})).pipe(map((label) => ({
|
|
412
464
|
...node,
|
|
413
|
-
label
|
|
414
|
-
|
|
415
|
-
valueFormatter,
|
|
416
|
-
}),
|
|
417
|
-
};
|
|
465
|
+
label,
|
|
466
|
+
})));
|
|
418
467
|
}
|
|
419
468
|
function createParentNodeKeysList(parentNode) {
|
|
420
469
|
if (!parentNode) {
|
|
@@ -422,20 +471,20 @@ function createParentNodeKeysList(parentNode) {
|
|
|
422
471
|
}
|
|
423
472
|
return [...parentNode.parentKeys, parentNode.key];
|
|
424
473
|
}
|
|
425
|
-
function
|
|
426
|
-
if (!
|
|
474
|
+
function createInstanceKeysFilteredQuery(query, targetInstanceKeys) {
|
|
475
|
+
if (!targetInstanceKeys || !targetInstanceKeys.length) {
|
|
427
476
|
return query;
|
|
428
477
|
}
|
|
429
478
|
const MAX_ALLOWED_BINDINGS = 1000;
|
|
430
|
-
if (
|
|
479
|
+
if (targetInstanceKeys.length < MAX_ALLOWED_BINDINGS) {
|
|
431
480
|
return {
|
|
432
481
|
...query,
|
|
433
482
|
ecsql: `
|
|
434
483
|
SELECT *
|
|
435
484
|
FROM (${query.ecsql}) q
|
|
436
|
-
WHERE q.ECInstanceId IN (${
|
|
485
|
+
WHERE q.ECInstanceId IN (${targetInstanceKeys.map(() => "?").join(",")})
|
|
437
486
|
`,
|
|
438
|
-
bindings: [...(query.bindings ?? []), ...
|
|
487
|
+
bindings: [...(query.bindings ?? []), ...targetInstanceKeys.map((k) => ({ type: "id", value: k.id }))],
|
|
439
488
|
};
|
|
440
489
|
}
|
|
441
490
|
/* c8 ignore start */
|
|
@@ -446,8 +495,78 @@ function filterQueryByInstanceKeys(query, filteredInstanceKeys) {
|
|
|
446
495
|
FROM (${query.ecsql}) q
|
|
447
496
|
WHERE InVirtualSet(?, q.ECInstanceId)
|
|
448
497
|
`,
|
|
449
|
-
bindings: [...(query.bindings ?? []), { type: "idset", value:
|
|
498
|
+
bindings: [...(query.bindings ?? []), { type: "idset", value: targetInstanceKeys.map((k) => k.id) }],
|
|
450
499
|
};
|
|
451
500
|
/* c8 ignore end */
|
|
452
501
|
}
|
|
502
|
+
function mergeNodes(source) {
|
|
503
|
+
return from(source).pipe(reduce((acc, input) => {
|
|
504
|
+
for (let i = 0; i < acc.length; ++i) {
|
|
505
|
+
if (input.imodelAccess === acc[i].imodelAccess) {
|
|
506
|
+
// don't attempt to merge nodes if they come from the same provider
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
// the first argument for `tryMergeNodes` acts as the primary data source, so we have to make sure we pass
|
|
510
|
+
// the node with higher `imodelAccessIndex` first
|
|
511
|
+
const candidates = input.imodelAccessIndex > acc[i].imodelAccessIndex
|
|
512
|
+
? { imodelAccess: input.imodelAccess, imodelAccessIndex: input.imodelAccessIndex, primary: input.node, secondary: acc[i].node }
|
|
513
|
+
: { imodelAccess: acc[i].imodelAccess, imodelAccessIndex: acc[i].imodelAccessIndex, primary: acc[i].node, secondary: input.node };
|
|
514
|
+
const merged = tryMergeNodes(candidates.primary, candidates.secondary);
|
|
515
|
+
if (merged) {
|
|
516
|
+
acc[i] = { node: merged, imodelAccess: candidates.imodelAccess, imodelAccessIndex: candidates.imodelAccessIndex };
|
|
517
|
+
return acc;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
acc.push(input);
|
|
521
|
+
return acc;
|
|
522
|
+
}, new Array()), mergeAll());
|
|
523
|
+
}
|
|
524
|
+
function mergeSearchProps(primary, secondary) {
|
|
525
|
+
if (!primary || !secondary) {
|
|
526
|
+
return primary ?? secondary;
|
|
527
|
+
}
|
|
528
|
+
const hasSearchTargetAncestor = primary.hasSearchTargetAncestor || secondary.hasSearchTargetAncestor;
|
|
529
|
+
const childrenTargetPaths = [...(primary.childrenTargetPaths ?? []), ...(secondary.childrenTargetPaths ?? [])];
|
|
530
|
+
return {
|
|
531
|
+
...(hasSearchTargetAncestor ? { hasSearchTargetAncestor } : undefined),
|
|
532
|
+
...(childrenTargetPaths.length ? { childrenTargetPaths } : undefined),
|
|
533
|
+
...(primary.isSearchTarget || secondary.isSearchTarget
|
|
534
|
+
? {
|
|
535
|
+
isSearchTarget: true,
|
|
536
|
+
searchTargetOptions: HierarchySearchPath.mergeOptions(primary.isSearchTarget ? primary.searchTargetOptions : undefined, secondary.isSearchTarget ? secondary.searchTargetOptions : undefined),
|
|
537
|
+
}
|
|
538
|
+
: {
|
|
539
|
+
isSearchTarget: false,
|
|
540
|
+
}),
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
function tryMergeInstanceNodes(primary, secondary) {
|
|
544
|
+
if (HierarchyNode.isInstancesNode(primary) &&
|
|
545
|
+
HierarchyNode.isInstancesNode(secondary) &&
|
|
546
|
+
primary.key.instanceKeys.some((lhsKey) => secondary.key.instanceKeys.some((rhsKey) => InstanceKey.equals(lhsKey, rhsKey)))) {
|
|
547
|
+
const searchProps = mergeSearchProps(primary.search, secondary.search);
|
|
548
|
+
return {
|
|
549
|
+
...primary,
|
|
550
|
+
key: {
|
|
551
|
+
type: "instances",
|
|
552
|
+
instanceKeys: primary.key.instanceKeys.concat(secondary.key.instanceKeys),
|
|
553
|
+
},
|
|
554
|
+
...(searchProps ? { search: searchProps } : undefined),
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
return undefined;
|
|
558
|
+
}
|
|
559
|
+
function tryMergeGenericNodes(primary, secondary) {
|
|
560
|
+
if (HierarchyNode.isGeneric(primary) && HierarchyNode.isGeneric(secondary) && primary.key.type === secondary.key.type) {
|
|
561
|
+
const searchProps = mergeSearchProps(primary.search, secondary.search);
|
|
562
|
+
return {
|
|
563
|
+
...primary,
|
|
564
|
+
...(searchProps ? { search: searchProps } : undefined),
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
return undefined;
|
|
568
|
+
}
|
|
569
|
+
function tryMergeNodes(primary, secondary) {
|
|
570
|
+
return tryMergeInstanceNodes(primary, secondary) ?? tryMergeGenericNodes(primary, secondary) ?? undefined;
|
|
571
|
+
}
|
|
453
572
|
//# sourceMappingURL=IModelHierarchyProvider.js.map
|