@itwin/tree-widget-react 4.0.0-alpha.25 → 4.0.0-alpha.26

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 (192) hide show
  1. package/CHANGELOG.md +35 -1
  2. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js +2 -1
  3. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  4. package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.js +1 -1
  5. package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.js.map +1 -1
  6. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +4 -1
  7. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +4 -1
  8. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  9. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +1 -0
  10. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +36 -47
  11. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  12. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +2 -0
  13. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js +4 -1
  14. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  15. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +2 -1
  16. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +75 -38
  17. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  18. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeNode.d.ts +3 -1
  19. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeNode.js.map +1 -1
  20. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +4 -2
  21. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +38 -23
  22. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  23. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +11 -21
  24. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +16 -168
  25. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  26. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.d.ts +65 -0
  27. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.js +22 -0
  28. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.js.map +1 -0
  29. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseSearchPaths.d.ts +2 -2
  30. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseSearchPaths.js +4 -4
  31. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseSearchPaths.js.map +1 -1
  32. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.d.ts +6 -10
  33. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.js +180 -88
  34. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.js.map +1 -1
  35. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.d.ts +14 -5
  36. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.js +43 -24
  37. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.js.map +1 -1
  38. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/SearchResultsTree.d.ts +3 -1
  39. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/SearchResultsTree.js +78 -17
  40. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/SearchResultsTree.js.map +1 -1
  41. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.d.ts +2 -0
  42. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js +4 -1
  43. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js.map +1 -1
  44. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js +91 -114
  45. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js.map +1 -1
  46. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.d.ts +2 -2
  47. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js.map +1 -1
  48. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeNode.d.ts +1 -3
  49. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeNode.js +2 -4
  50. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeNode.js.map +1 -1
  51. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.d.ts +13 -1
  52. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js +62 -32
  53. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js.map +1 -1
  54. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTreeDefinition.d.ts +12 -9
  55. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTreeDefinition.js +42 -38
  56. package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTreeDefinition.js.map +1 -1
  57. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.d.ts +15 -38
  58. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js +59 -242
  59. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js.map +1 -1
  60. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.d.ts +29 -0
  61. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.js +19 -0
  62. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.js.map +1 -0
  63. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.d.ts +4 -8
  64. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.js +154 -78
  65. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.js.map +1 -1
  66. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHelper.js +20 -6
  67. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHelper.js.map +1 -1
  68. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/SearchResultsTree.d.ts +6 -10
  69. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/SearchResultsTree.js +104 -63
  70. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/SearchResultsTree.js.map +1 -1
  71. package/lib/esm/tree-widget-react/components/trees/common/SharedTreeContextProvider.d.ts +7 -0
  72. package/lib/esm/tree-widget-react/components/trees/common/SharedTreeContextProvider.js +14 -0
  73. package/lib/esm/tree-widget-react/components/trees/common/SharedTreeContextProvider.js.map +1 -0
  74. package/lib/esm/tree-widget-react/components/trees/common/TreeWidgetViewport.js +1 -1
  75. package/lib/esm/tree-widget-react/components/trees/common/TreeWidgetViewport.js.map +1 -1
  76. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js +2 -2
  77. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  78. package/lib/esm/tree-widget-react/components/trees/common/Utils.js +2 -2
  79. package/lib/esm/tree-widget-react/components/trees/common/Utils.js.map +1 -1
  80. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.d.ts +4 -4
  81. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js +1 -1
  82. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  83. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.d.ts +4 -4
  84. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.js.map +1 -1
  85. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js +7 -5
  86. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  87. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.d.ts +2 -2
  88. package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.js.map +1 -1
  89. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js +5 -5
  90. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  91. package/lib/esm/tree-widget-react/components/trees/common/internal/SharedTreeContextProviderInternal.d.ts +20 -0
  92. package/lib/esm/tree-widget-react/components/trees/common/internal/SharedTreeContextProviderInternal.js +44 -0
  93. package/lib/esm/tree-widget-react/components/trees/common/internal/SharedTreeContextProviderInternal.js.map +1 -0
  94. package/lib/esm/tree-widget-react/components/trees/common/internal/Types.d.ts +4 -0
  95. package/lib/esm/tree-widget-react/components/trees/common/internal/Types.js.map +1 -1
  96. package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.d.ts +12 -0
  97. package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.js +2 -1
  98. package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.js.map +1 -1
  99. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +17 -6
  100. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +58 -29
  101. package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -1
  102. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.d.ts +8 -14
  103. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js +22 -26
  104. package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js.map +1 -1
  105. package/lib/esm/tree-widget-react/components/trees/common/internal/{AlwaysAndNeverDrawnElementInfo.d.ts → caches/AlwaysAndNeverDrawnElementInfoCache.d.ts} +15 -21
  106. package/lib/esm/tree-widget-react/components/trees/common/internal/{AlwaysAndNeverDrawnElementInfo.js → caches/AlwaysAndNeverDrawnElementInfoCache.js} +40 -38
  107. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/AlwaysAndNeverDrawnElementInfoCache.js.map +1 -0
  108. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.d.ts +68 -0
  109. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.js +148 -0
  110. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.js.map +1 -0
  111. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.d.ts +30 -0
  112. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.js +151 -0
  113. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.js.map +1 -0
  114. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.d.ts +32 -0
  115. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.js +106 -0
  116. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.js.map +1 -0
  117. package/lib/esm/tree-widget-react/components/trees/common/internal/{ModelCategoryElementsCountCache.d.ts → caches/ModelCategoryElementsCountCache.d.ts} +9 -2
  118. package/lib/esm/tree-widget-react/components/trees/common/internal/{ModelCategoryElementsCountCache.js → caches/ModelCategoryElementsCountCache.js} +17 -21
  119. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModelCategoryElementsCountCache.js.map +1 -0
  120. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.d.ts +27 -0
  121. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.js +106 -0
  122. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.js.map +1 -0
  123. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/SubCategoriesCache.d.ts +23 -0
  124. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/SubCategoriesCache.js +56 -0
  125. package/lib/esm/tree-widget-react/components/trees/common/internal/caches/SubCategoriesCache.js.map +1 -0
  126. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.d.ts +6 -6
  127. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js +27 -17
  128. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js.map +1 -1
  129. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts +7 -13
  130. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js +36 -35
  131. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -1
  132. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseSearchResultsTree.d.ts +18 -0
  133. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseSearchResultsTree.js +14 -1
  134. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseSearchResultsTree.js.map +1 -1
  135. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.d.ts +46 -70
  136. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.js +229 -361
  137. package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.js.map +1 -1
  138. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.d.ts +2 -2
  139. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
  140. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js.map +1 -1
  141. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +2 -2
  142. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
  143. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js.map +1 -1
  144. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +1 -1
  145. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
  146. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +32 -19
  147. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
  148. package/lib/esm/tree-widget-react/components/trees/index.d.ts +2 -1
  149. package/lib/esm/tree-widget-react/components/trees/index.js +2 -1
  150. package/lib/esm/tree-widget-react/components/trees/index.js.map +1 -1
  151. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +4 -1
  152. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js +4 -1
  153. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  154. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.d.ts +7 -3
  155. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +36 -35
  156. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  157. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.d.ts +1 -0
  158. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js +3 -1
  159. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  160. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +1 -0
  161. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +56 -26
  162. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  163. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.d.ts +5 -3
  164. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +25 -12
  165. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  166. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +11 -23
  167. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +56 -189
  168. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  169. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.d.ts +52 -0
  170. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.js +22 -0
  171. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.js.map +1 -0
  172. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseSearchPaths.d.ts +2 -2
  173. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseSearchPaths.js +8 -8
  174. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseSearchPaths.js.map +1 -1
  175. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.d.ts +6 -10
  176. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.js +179 -72
  177. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.js.map +1 -1
  178. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.d.ts +6 -0
  179. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.js +20 -8
  180. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.js.map +1 -1
  181. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/SearchResultsTree.d.ts +4 -2
  182. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/SearchResultsTree.js +73 -13
  183. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/SearchResultsTree.js.map +1 -1
  184. package/lib/esm/tree-widget-react-internal.d.ts +1 -0
  185. package/lib/esm/tree-widget-react-internal.js +1 -0
  186. package/lib/esm/tree-widget-react-internal.js.map +1 -1
  187. package/package.json +77 -82
  188. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseSearchPaths.d.ts +0 -20
  189. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseSearchPaths.js +0 -53
  190. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseSearchPaths.js.map +0 -1
  191. package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.js.map +0 -1
  192. package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js.map +0 -1
@@ -0,0 +1,151 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { defaultIfEmpty, defer, EMPTY, firstValueFrom, from, map, mergeMap, reduce, tap } from "rxjs";
6
+ import { Guid, Id64 } from "@itwin/core-bentley";
7
+ import { catchBeSQLiteInterrupts } from "../UseErrorState.js";
8
+ import { getOptimalBatchSize } from "../Utils.js";
9
+ /** @internal */
10
+ export class ElementChildrenCache {
11
+ #queryExecutor;
12
+ #elementClassName;
13
+ #componentId;
14
+ #componentName;
15
+ #childElementsMap;
16
+ /** Stores element ids which have children query scheduled to execute. */
17
+ #childElementsLoadingMap;
18
+ constructor(props) {
19
+ this.#queryExecutor = props.queryExecutor;
20
+ this.#elementClassName = props.elementClassName;
21
+ this.#componentId = props.componentId;
22
+ this.#componentName = "ElementChildrenCache";
23
+ this.#childElementsMap = new Map();
24
+ this.#childElementsLoadingMap = new Map();
25
+ }
26
+ queryChildren({ elementIds }) {
27
+ if (elementIds.length === 0) {
28
+ return EMPTY;
29
+ }
30
+ return defer(() => {
31
+ const ctes = [
32
+ `
33
+ ElementChildren(id, parentId) AS (
34
+ SELECT ECInstanceId id, Parent.Id parentId
35
+ FROM ${this.#elementClassName}
36
+ WHERE Parent.Id IN (${elementIds.join(", ")})
37
+ UNION ALL
38
+ SELECT c.ECInstanceId id, c.Parent.Id
39
+ FROM ${this.#elementClassName} c
40
+ JOIN ElementChildren p ON c.Parent.Id = p.id
41
+ )
42
+ `,
43
+ ];
44
+ const ecsql = `
45
+ SELECT id, parentId
46
+ FROM ElementChildren
47
+ `;
48
+ return this.#queryExecutor.createQueryReader({ ecsql, ctes }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/children/${Guid.createValue()}` });
49
+ }).pipe(catchBeSQLiteInterrupts, map((row) => {
50
+ return { id: row.id, parentId: row.parentId };
51
+ }));
52
+ }
53
+ getChildElementsTreeFromMap({ elementIds }) {
54
+ const result = new Map();
55
+ if (Id64.sizeOf(elementIds) === 0 || this.#childElementsMap.size === 0) {
56
+ return result;
57
+ }
58
+ for (const elementId of Id64.iterable(elementIds)) {
59
+ const entry = this.#childElementsMap.get(elementId);
60
+ if (!entry?.children) {
61
+ continue;
62
+ }
63
+ const elementChildrenTree = new Map();
64
+ result.set(elementId, { children: elementChildrenTree });
65
+ for (const childId of entry.children) {
66
+ const childrenTreeOfChild = this.getChildElementsTreeFromMap({ elementIds: childId });
67
+ // Need to add children tree created from childId. This tree includes childId as root element
68
+ // If child does not have children, children tree won't be created. Need to add childId with undefined children
69
+ elementChildrenTree.set(childId, { children: childrenTreeOfChild.size > 0 ? childrenTreeOfChild : undefined });
70
+ }
71
+ }
72
+ return result;
73
+ }
74
+ getChildElementsCountMap({ elementIds }) {
75
+ const result = new Map();
76
+ for (const elementId of Id64.iterable(elementIds)) {
77
+ const entry = this.#childElementsMap.get(elementId);
78
+ if (entry?.children) {
79
+ let totalChildrenCount = entry.children.length;
80
+ for (const childrenOfChildCount of this.getChildElementsCountMap({ elementIds: entry.children }).values()) {
81
+ totalChildrenCount += childrenOfChildCount;
82
+ }
83
+ result.set(elementId, totalChildrenCount);
84
+ }
85
+ }
86
+ return result;
87
+ }
88
+ /**
89
+ * Populates #childElementsLoadingMap with promises. When these promises resolve, they will populate #childElementsMap with values and delete entries from #childElementsLoadingMap.
90
+ */
91
+ createChildElementsLoadingMapEntries({ elementsToQuery }) {
92
+ const getElementsToQueryPromise = async (batchedElementsToQuery) => firstValueFrom(this.queryChildren({ elementIds: batchedElementsToQuery }).pipe(
93
+ // Want to have void at the end instead of void[], so using reduce
94
+ reduce((acc, { parentId, id }) => {
95
+ let entry = this.#childElementsMap.get(parentId);
96
+ if (!entry) {
97
+ entry = { children: [] };
98
+ this.#childElementsMap.set(parentId, entry);
99
+ }
100
+ if (!entry.children) {
101
+ entry.children = [];
102
+ }
103
+ // Add child to parent's entry and add child to children map
104
+ entry.children.push(id);
105
+ if (!this.#childElementsMap.has(id)) {
106
+ this.#childElementsMap.set(id, { children: undefined });
107
+ }
108
+ return acc;
109
+ }, (() => { })()), tap({ complete: () => batchedElementsToQuery.forEach((elementId) => this.#childElementsLoadingMap.delete(elementId)) }), defaultIfEmpty((() => { })())));
110
+ const maximumBatchSize = 1000;
111
+ const totalSize = elementsToQuery.length;
112
+ const optimalBatchSize = getOptimalBatchSize({ totalSize, maximumBatchSize });
113
+ const loadingMapEntries = new Array();
114
+ // Don't want to slice if its not necessary
115
+ if (totalSize <= maximumBatchSize) {
116
+ loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery));
117
+ }
118
+ else {
119
+ for (let i = 0; i < elementsToQuery.length; i += optimalBatchSize) {
120
+ loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery.slice(i, i + optimalBatchSize)));
121
+ }
122
+ }
123
+ elementsToQuery.forEach((elementId, index) => this.#childElementsLoadingMap.set(elementId, loadingMapEntries[Math.floor(index / optimalBatchSize)]));
124
+ return { loadingMapEntries: Promise.all(loadingMapEntries).then(() => { }) };
125
+ }
126
+ createChildElementsMapEntries({ elementIds }) {
127
+ return from(Id64.iterable(elementIds)).pipe(reduce((acc, elementId) => {
128
+ if (this.#childElementsMap.has(elementId)) {
129
+ return acc;
130
+ }
131
+ const loadingPromise = this.#childElementsLoadingMap.get(elementId);
132
+ if (loadingPromise) {
133
+ acc.existingPromises.push(loadingPromise);
134
+ }
135
+ else {
136
+ acc.elementsToQuery.push(elementId);
137
+ }
138
+ return acc;
139
+ }, { existingPromises: new Array(), elementsToQuery: new Array() }), mergeMap(async ({ elementsToQuery, existingPromises }) => {
140
+ existingPromises.push(this.createChildElementsLoadingMapEntries({ elementsToQuery }).loadingMapEntries);
141
+ return Promise.all(existingPromises);
142
+ }));
143
+ }
144
+ getChildElementsTree({ elementIds }) {
145
+ return this.createChildElementsMapEntries({ elementIds }).pipe(map(() => this.getChildElementsTreeFromMap({ elementIds })));
146
+ }
147
+ getAllChildElementsCount({ elementIds }) {
148
+ return this.createChildElementsMapEntries({ elementIds }).pipe(map(() => this.getChildElementsCountMap({ elementIds })));
149
+ }
150
+ }
151
+ //# sourceMappingURL=ElementChildrenCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElementChildrenCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.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 { defaultIfEmpty, defer, EMPTY, firstValueFrom, from, map, mergeMap, reduce, tap } from \"rxjs\";\nimport { Guid, Id64 } from \"@itwin/core-bentley\";\nimport { catchBeSQLiteInterrupts } from \"../UseErrorState.js\";\nimport { getOptimalBatchSize } from \"../Utils.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { GuidString, Id64Arg, Id64Array, Id64String } from \"@itwin/core-bentley\";\nimport type { LimitingECSqlQueryExecutor } from \"@itwin/presentation-hierarchies\";\nimport type { ChildrenTree } from \"../Utils.js\";\n\ntype ChildElementsMap = Map<Id64String, { children: Id64Array | undefined }>;\ntype ChildElementsLoadingMap = Map<Id64String, Promise<void>>;\n\ninterface ElementChildrenCacheProps {\n queryExecutor: LimitingECSqlQueryExecutor;\n elementClassName: string;\n componentId: GuidString;\n}\n\n/** @internal */\nexport class ElementChildrenCache {\n #queryExecutor: LimitingECSqlQueryExecutor;\n readonly #elementClassName: string;\n #componentId: GuidString;\n #componentName: string;\n #childElementsMap: ChildElementsMap;\n /** Stores element ids which have children query scheduled to execute. */\n #childElementsLoadingMap: ChildElementsLoadingMap;\n\n constructor(props: ElementChildrenCacheProps) {\n this.#queryExecutor = props.queryExecutor;\n this.#elementClassName = props.elementClassName;\n this.#componentId = props.componentId;\n this.#componentName = \"ElementChildrenCache\";\n this.#childElementsMap = new Map();\n this.#childElementsLoadingMap = new Map();\n }\n\n private queryChildren({ elementIds }: { elementIds: Id64Array }): Observable<{ id: Id64String; parentId: Id64String }> {\n if (elementIds.length === 0) {\n return EMPTY;\n }\n\n return defer(() => {\n const ctes = [\n `\n ElementChildren(id, parentId) AS (\n SELECT ECInstanceId id, Parent.Id parentId\n FROM ${this.#elementClassName}\n WHERE Parent.Id IN (${elementIds.join(\", \")})\n UNION ALL\n SELECT c.ECInstanceId id, c.Parent.Id\n FROM ${this.#elementClassName} c\n JOIN ElementChildren p ON c.Parent.Id = p.id\n )\n `,\n ];\n const ecsql = `\n SELECT id, parentId\n FROM ElementChildren\n `;\n return this.#queryExecutor.createQueryReader(\n { ecsql, ctes },\n { rowFormat: \"ECSqlPropertyNames\", limit: \"unbounded\", restartToken: `${this.#componentName}/${this.#componentId}/children/${Guid.createValue()}` },\n );\n }).pipe(\n catchBeSQLiteInterrupts,\n map((row) => {\n return { id: row.id, parentId: row.parentId };\n }),\n );\n }\n\n private getChildElementsTreeFromMap({ elementIds }: { elementIds: Id64Arg }): ChildrenTree {\n const result: ChildrenTree = new Map();\n if (Id64.sizeOf(elementIds) === 0 || this.#childElementsMap.size === 0) {\n return result;\n }\n for (const elementId of Id64.iterable(elementIds)) {\n const entry = this.#childElementsMap.get(elementId);\n if (!entry?.children) {\n continue;\n }\n const elementChildrenTree: ChildrenTree = new Map();\n result.set(elementId, { children: elementChildrenTree });\n for (const childId of entry.children) {\n const childrenTreeOfChild = this.getChildElementsTreeFromMap({ elementIds: childId });\n // Need to add children tree created from childId. This tree includes childId as root element\n // If child does not have children, children tree won't be created. Need to add childId with undefined children\n elementChildrenTree.set(childId, { children: childrenTreeOfChild.size > 0 ? childrenTreeOfChild : undefined });\n }\n }\n return result;\n }\n\n private getChildElementsCountMap({ elementIds }: { elementIds: Id64Arg }): Map<Id64String, number> {\n const result = new Map<Id64String, number>();\n for (const elementId of Id64.iterable(elementIds)) {\n const entry = this.#childElementsMap.get(elementId);\n if (entry?.children) {\n let totalChildrenCount = entry.children.length;\n for (const childrenOfChildCount of this.getChildElementsCountMap({ elementIds: entry.children }).values()) {\n totalChildrenCount += childrenOfChildCount;\n }\n result.set(elementId, totalChildrenCount);\n }\n }\n return result;\n }\n\n /**\n * Populates #childElementsLoadingMap with promises. When these promises resolve, they will populate #childElementsMap with values and delete entries from #childElementsLoadingMap.\n */\n private createChildElementsLoadingMapEntries({ elementsToQuery }: { elementsToQuery: Id64Array }): { loadingMapEntries: Promise<void> } {\n const getElementsToQueryPromise = async (batchedElementsToQuery: Id64Array) =>\n firstValueFrom(\n this.queryChildren({ elementIds: batchedElementsToQuery }).pipe(\n // Want to have void at the end instead of void[], so using reduce\n reduce(\n (acc, { parentId, id }) => {\n let entry = this.#childElementsMap.get(parentId);\n if (!entry) {\n entry = { children: [] };\n this.#childElementsMap.set(parentId, entry);\n }\n if (!entry.children) {\n entry.children = [];\n }\n // Add child to parent's entry and add child to children map\n entry.children.push(id);\n if (!this.#childElementsMap.has(id)) {\n this.#childElementsMap.set(id, { children: undefined });\n }\n return acc;\n },\n (() => {})(),\n ),\n tap({ complete: () => batchedElementsToQuery.forEach((elementId) => this.#childElementsLoadingMap.delete(elementId)) }),\n defaultIfEmpty((() => {})()),\n ),\n );\n const maximumBatchSize = 1000;\n const totalSize = elementsToQuery.length;\n const optimalBatchSize = getOptimalBatchSize({ totalSize, maximumBatchSize });\n const loadingMapEntries = new Array<Promise<void>>();\n // Don't want to slice if its not necessary\n if (totalSize <= maximumBatchSize) {\n loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery));\n } else {\n for (let i = 0; i < elementsToQuery.length; i += optimalBatchSize) {\n loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery.slice(i, i + optimalBatchSize)));\n }\n }\n\n elementsToQuery.forEach((elementId, index) => this.#childElementsLoadingMap.set(elementId, loadingMapEntries[Math.floor(index / optimalBatchSize)]));\n return { loadingMapEntries: Promise.all(loadingMapEntries).then(() => {}) };\n }\n\n private createChildElementsMapEntries({ elementIds }: { elementIds: Id64Arg }): Observable<void[]> {\n return from(Id64.iterable(elementIds)).pipe(\n reduce(\n (acc, elementId) => {\n if (this.#childElementsMap.has(elementId)) {\n return acc;\n }\n const loadingPromise = this.#childElementsLoadingMap.get(elementId);\n if (loadingPromise) {\n acc.existingPromises.push(loadingPromise);\n } else {\n acc.elementsToQuery.push(elementId);\n }\n return acc;\n },\n { existingPromises: new Array<Promise<void>>(), elementsToQuery: new Array<Id64String>() },\n ),\n mergeMap(async ({ elementsToQuery, existingPromises }) => {\n existingPromises.push(this.createChildElementsLoadingMapEntries({ elementsToQuery }).loadingMapEntries);\n return Promise.all(existingPromises);\n }),\n );\n }\n\n public getChildElementsTree({ elementIds }: { elementIds: Id64Arg }): Observable<ChildrenTree> {\n return this.createChildElementsMapEntries({ elementIds }).pipe(map(() => this.getChildElementsTreeFromMap({ elementIds })));\n }\n\n public getAllChildElementsCount({ elementIds }: { elementIds: Id64Arg }): Observable<Map<Id64String, number>> {\n return this.createChildElementsMapEntries({ elementIds }).pipe(map(() => this.getChildElementsCountMap({ elementIds })));\n }\n}\n"]}
@@ -0,0 +1,32 @@
1
+ import type { Observable } from "rxjs";
2
+ import type { GuidString, Id64Array, Id64Set, Id64String } from "@itwin/core-bentley";
3
+ import type { LimitingECSqlQueryExecutor } from "@itwin/presentation-hierarchies";
4
+ import type { ModelId } from "../Types.js";
5
+ import type { ModeledElementsCache } from "./ModeledElementsCache.js";
6
+ interface ElementModelCategoriesCacheProps {
7
+ queryExecutor: LimitingECSqlQueryExecutor;
8
+ componentId: GuidString;
9
+ elementClassName: string;
10
+ modeledElementsCache: ModeledElementsCache;
11
+ }
12
+ /** @internal */
13
+ export declare class ElementModelCategoriesCache {
14
+ #private;
15
+ constructor(props: ElementModelCategoriesCacheProps);
16
+ private queryElementModelCategories;
17
+ private getModelsCategoriesInfo;
18
+ getCategoryElementModels(props: {
19
+ categoryId: Id64String;
20
+ includeSubModels?: boolean;
21
+ includeOnlyIfCategoryOfTopMostElement?: boolean;
22
+ }): Observable<Array<ModelId>>;
23
+ getModelCategoryIds({ modelId, includeOnlyIfCategoryOfTopMostElement, }: {
24
+ modelId: Id64String;
25
+ includeOnlyIfCategoryOfTopMostElement?: boolean;
26
+ }): Observable<Id64Set>;
27
+ getCategoriesOfModelsTopMostElements(modelIds: Id64Array): Observable<Id64Set>;
28
+ getAllCategoriesOfElements(): Observable<Id64Set>;
29
+ getAllModels(): Observable<Array<ModelId>>;
30
+ }
31
+ export {};
32
+ //# sourceMappingURL=ElementModelCategoriesCache.d.ts.map
@@ -0,0 +1,106 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { defer, forkJoin, from, map, mergeMap, reduce, shareReplay } from "rxjs";
6
+ import { CLASS_NAME_Model } from "../ClassNameDefinitions.js";
7
+ import { catchBeSQLiteInterrupts } from "../UseErrorState.js";
8
+ /** @internal */
9
+ export class ElementModelCategoriesCache {
10
+ #queryExecutor;
11
+ #componentId;
12
+ #componentName;
13
+ #elementClassName;
14
+ #modeledElementsCache;
15
+ #modelsCategoriesInfo;
16
+ constructor(props) {
17
+ this.#queryExecutor = props.queryExecutor;
18
+ this.#elementClassName = props.elementClassName;
19
+ this.#modeledElementsCache = props.modeledElementsCache;
20
+ this.#componentId = props.componentId;
21
+ this.#componentName = "ElementModelCategoriesCache";
22
+ }
23
+ queryElementModelCategories() {
24
+ return defer(() => {
25
+ const query = `
26
+ SELECT * FROM (
27
+ SELECT
28
+ this.Model.Id modelId,
29
+ this.Category.Id categoryId,
30
+ MAX(IIF(this.Parent.Id IS NULL, 1, 0)) isTopMostElementCategory
31
+ FROM ${CLASS_NAME_Model} m
32
+ JOIN ${this.#elementClassName} this ON m.ECInstanceId = this.Model.Id
33
+ WHERE m.IsPrivate = false
34
+ GROUP BY modelId, categoryId
35
+ )
36
+ `;
37
+ return this.#queryExecutor.createQueryReader({ ecsql: query }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/element-models-and-categories` });
38
+ }).pipe(catchBeSQLiteInterrupts, map((row) => {
39
+ return { modelId: row.modelId, categoryId: row.categoryId, isTopMostElementCategory: !!row.isTopMostElementCategory };
40
+ }));
41
+ }
42
+ getModelsCategoriesInfo() {
43
+ this.#modelsCategoriesInfo ??= forkJoin({
44
+ modelCategories: this.queryElementModelCategories().pipe(reduce((acc, queriedCategory) => {
45
+ let modelEntry = acc.get(queriedCategory.modelId);
46
+ if (modelEntry === undefined) {
47
+ modelEntry = { categoriesOfTopMostElements: new Set(), allCategories: new Set() };
48
+ acc.set(queriedCategory.modelId, modelEntry);
49
+ }
50
+ modelEntry.allCategories.add(queriedCategory.categoryId);
51
+ if (queriedCategory.isTopMostElementCategory) {
52
+ modelEntry.categoriesOfTopMostElements.add(queriedCategory.categoryId);
53
+ }
54
+ return acc;
55
+ }, new Map())),
56
+ allSubModels: this.#modeledElementsCache.getModeledElementsInfo().pipe(map(({ allSubModels }) => allSubModels)),
57
+ }).pipe(map(({ modelCategories, allSubModels }) => {
58
+ const result = new Map();
59
+ for (const [modelId, { categoriesOfTopMostElements, allCategories }] of modelCategories) {
60
+ const isSubModel = allSubModels.has(modelId);
61
+ result.set(modelId, {
62
+ categoriesOfTopMostElements,
63
+ allCategories,
64
+ isSubModel,
65
+ });
66
+ }
67
+ return result;
68
+ }), shareReplay());
69
+ return this.#modelsCategoriesInfo;
70
+ }
71
+ getCategoryElementModels(props) {
72
+ const { categoryId, includeSubModels } = props;
73
+ return this.getModelsCategoriesInfo().pipe(map((modelCategories) => {
74
+ const categoryModels = new Array();
75
+ for (const [modelId, { allCategories, categoriesOfTopMostElements, isSubModel }] of modelCategories) {
76
+ if ((includeSubModels || !isSubModel) &&
77
+ (props.includeOnlyIfCategoryOfTopMostElement ? categoriesOfTopMostElements.has(categoryId) : allCategories.has(categoryId))) {
78
+ categoryModels.push(modelId);
79
+ }
80
+ }
81
+ return categoryModels;
82
+ }));
83
+ }
84
+ getModelCategoryIds({ modelId, includeOnlyIfCategoryOfTopMostElement, }) {
85
+ return this.getModelsCategoriesInfo().pipe(map((modelCategories) => (includeOnlyIfCategoryOfTopMostElement ? modelCategories.get(modelId)?.categoriesOfTopMostElements : modelCategories.get(modelId)?.allCategories) ??
86
+ new Set()));
87
+ }
88
+ getCategoriesOfModelsTopMostElements(modelIds) {
89
+ return this.getModelsCategoriesInfo().pipe(mergeMap((modelCategories) => from(modelIds).pipe(mergeMap((modelId) => modelCategories.get(modelId)?.categoriesOfTopMostElements ?? []))), reduce((acc, categoryId) => {
90
+ acc.add(categoryId);
91
+ return acc;
92
+ }, new Set()));
93
+ }
94
+ getAllCategoriesOfElements() {
95
+ return this.getModelsCategoriesInfo().pipe(mergeMap((modelCategories) => modelCategories.values()), reduce((acc, { allCategories }) => {
96
+ for (const categoryId of allCategories) {
97
+ acc.add(categoryId);
98
+ }
99
+ return acc;
100
+ }, new Set()));
101
+ }
102
+ getAllModels() {
103
+ return this.getModelsCategoriesInfo().pipe(map((modelCategories) => [...modelCategories.keys()]));
104
+ }
105
+ }
106
+ //# sourceMappingURL=ElementModelCategoriesCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElementModelCategoriesCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.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, forkJoin, from, map, mergeMap, reduce, shareReplay } from \"rxjs\";\nimport { CLASS_NAME_Model } from \"../ClassNameDefinitions.js\";\nimport { catchBeSQLiteInterrupts } from \"../UseErrorState.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { GuidString, Id64Array, Id64Set, Id64String } from \"@itwin/core-bentley\";\nimport type { LimitingECSqlQueryExecutor } from \"@itwin/presentation-hierarchies\";\nimport type { CategoryId, ModelId } from \"../Types.js\";\nimport type { ModeledElementsCache } from \"./ModeledElementsCache.js\";\n\ninterface ElementModelCategoriesCacheProps {\n queryExecutor: LimitingECSqlQueryExecutor;\n componentId: GuidString;\n elementClassName: string;\n modeledElementsCache: ModeledElementsCache;\n}\n\n/** @internal */\nexport class ElementModelCategoriesCache {\n #queryExecutor: LimitingECSqlQueryExecutor;\n #componentId: GuidString;\n #componentName: string;\n #elementClassName: string;\n #modeledElementsCache: ModeledElementsCache;\n #modelsCategoriesInfo:\n | Observable<Map<ModelId, { categoriesOfTopMostElements: Set<CategoryId>; allCategories: Set<CategoryId>; isSubModel: boolean }>>\n | undefined;\n\n constructor(props: ElementModelCategoriesCacheProps) {\n this.#queryExecutor = props.queryExecutor;\n this.#elementClassName = props.elementClassName;\n this.#modeledElementsCache = props.modeledElementsCache;\n this.#componentId = props.componentId;\n this.#componentName = \"ElementModelCategoriesCache\";\n }\n\n private queryElementModelCategories(): Observable<{\n modelId: Id64String;\n categoryId: Id64String;\n isTopMostElementCategory: boolean;\n }> {\n return defer(() => {\n const query = `\n SELECT * FROM (\n SELECT\n this.Model.Id modelId,\n this.Category.Id categoryId,\n MAX(IIF(this.Parent.Id IS NULL, 1, 0)) isTopMostElementCategory\n FROM ${CLASS_NAME_Model} m\n JOIN ${this.#elementClassName} this ON m.ECInstanceId = this.Model.Id\n WHERE m.IsPrivate = false\n GROUP BY modelId, categoryId\n )\n `;\n return this.#queryExecutor.createQueryReader(\n { ecsql: query },\n { rowFormat: \"ECSqlPropertyNames\", limit: \"unbounded\", restartToken: `${this.#componentName}/${this.#componentId}/element-models-and-categories` },\n );\n }).pipe(\n catchBeSQLiteInterrupts,\n map((row) => {\n return { modelId: row.modelId, categoryId: row.categoryId, isTopMostElementCategory: !!row.isTopMostElementCategory };\n }),\n );\n }\n\n private getModelsCategoriesInfo() {\n this.#modelsCategoriesInfo ??= forkJoin({\n modelCategories: this.queryElementModelCategories().pipe(\n reduce((acc, queriedCategory) => {\n let modelEntry = acc.get(queriedCategory.modelId);\n if (modelEntry === undefined) {\n modelEntry = { categoriesOfTopMostElements: new Set(), allCategories: new Set() };\n acc.set(queriedCategory.modelId, modelEntry);\n }\n modelEntry.allCategories.add(queriedCategory.categoryId);\n if (queriedCategory.isTopMostElementCategory) {\n modelEntry.categoriesOfTopMostElements.add(queriedCategory.categoryId);\n }\n return acc;\n }, new Map<ModelId, { categoriesOfTopMostElements: Set<CategoryId>; allCategories: Set<CategoryId> }>()),\n ),\n allSubModels: this.#modeledElementsCache.getModeledElementsInfo().pipe(map(({ allSubModels }) => allSubModels)),\n }).pipe(\n map(({ modelCategories, allSubModels }) => {\n const result = new Map<ModelId, { categoriesOfTopMostElements: Set<CategoryId>; allCategories: Set<CategoryId>; isSubModel: boolean }>();\n for (const [modelId, { categoriesOfTopMostElements, allCategories }] of modelCategories) {\n const isSubModel = allSubModels.has(modelId);\n result.set(modelId, {\n categoriesOfTopMostElements,\n allCategories,\n isSubModel,\n });\n }\n return result;\n }),\n shareReplay(),\n );\n return this.#modelsCategoriesInfo;\n }\n\n public getCategoryElementModels(props: {\n categoryId: Id64String;\n includeSubModels?: boolean;\n includeOnlyIfCategoryOfTopMostElement?: boolean;\n }): Observable<Array<ModelId>> {\n const { categoryId, includeSubModels } = props;\n return this.getModelsCategoriesInfo().pipe(\n map((modelCategories) => {\n const categoryModels = new Array<ModelId>();\n for (const [modelId, { allCategories, categoriesOfTopMostElements, isSubModel }] of modelCategories) {\n if (\n (includeSubModels || !isSubModel) &&\n (props.includeOnlyIfCategoryOfTopMostElement ? categoriesOfTopMostElements.has(categoryId) : allCategories.has(categoryId))\n ) {\n categoryModels.push(modelId);\n }\n }\n return categoryModels;\n }),\n );\n }\n\n public getModelCategoryIds({\n modelId,\n includeOnlyIfCategoryOfTopMostElement,\n }: {\n modelId: Id64String;\n includeOnlyIfCategoryOfTopMostElement?: boolean;\n }): Observable<Id64Set> {\n return this.getModelsCategoriesInfo().pipe(\n map(\n (modelCategories) =>\n (includeOnlyIfCategoryOfTopMostElement ? modelCategories.get(modelId)?.categoriesOfTopMostElements : modelCategories.get(modelId)?.allCategories) ??\n new Set(),\n ),\n );\n }\n\n public getCategoriesOfModelsTopMostElements(modelIds: Id64Array): Observable<Id64Set> {\n return this.getModelsCategoriesInfo().pipe(\n mergeMap((modelCategories) => from(modelIds).pipe(mergeMap((modelId) => modelCategories.get(modelId)?.categoriesOfTopMostElements ?? []))),\n reduce((acc, categoryId) => {\n acc.add(categoryId);\n return acc;\n }, new Set<Id64String>()),\n );\n }\n\n public getAllCategoriesOfElements(): Observable<Id64Set> {\n return this.getModelsCategoriesInfo().pipe(\n mergeMap((modelCategories) => modelCategories.values()),\n reduce((acc, { allCategories }) => {\n for (const categoryId of allCategories) {\n acc.add(categoryId);\n }\n return acc;\n }, new Set<CategoryId>()),\n );\n }\n\n public getAllModels(): Observable<Array<ModelId>> {\n return this.getModelsCategoriesInfo().pipe(map((modelCategories) => [...modelCategories.keys()]));\n }\n}\n"]}
@@ -4,9 +4,16 @@ import type { LimitingECSqlQueryExecutor } from "@itwin/presentation-hierarchies
4
4
  /** @internal */
5
5
  export declare class ModelCategoryElementsCountCache implements Disposable {
6
6
  #private;
7
- constructor(queryExecutor: LimitingECSqlQueryExecutor, elementsClassNames: string[], componentId: GuidString);
7
+ constructor(props: {
8
+ queryExecutor: LimitingECSqlQueryExecutor;
9
+ elementClassName: string;
10
+ componentId: GuidString;
11
+ });
8
12
  private queryCategoryElementCounts;
9
13
  [Symbol.dispose](): void;
10
- getCategoryElementsCount(modelId: Id64String, categoryId: Id64String): Observable<number>;
14
+ getCategoryElementsCount({ modelId, categoryId }: {
15
+ modelId: Id64String;
16
+ categoryId: Id64String;
17
+ }): Observable<number>;
11
18
  }
12
19
  //# sourceMappingURL=ModelCategoryElementsCountCache.d.ts.map
@@ -4,21 +4,21 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import { bufferCount, bufferTime, defer, filter, from, map, mergeAll, mergeMap, reduce, ReplaySubject, Subject, take, toArray } from "rxjs";
6
6
  import { assert, Guid } from "@itwin/core-bentley";
7
- import { catchBeSQLiteInterrupts } from "./UseErrorState.js";
8
- import { releaseMainThreadOnItemsCount } from "./Utils.js";
7
+ import { catchBeSQLiteInterrupts } from "../UseErrorState.js";
8
+ import { releaseMainThreadOnItemsCount } from "../Utils.js";
9
9
  /** @internal */
10
10
  export class ModelCategoryElementsCountCache {
11
11
  #cache = new Map();
12
12
  #requestsStream = new Subject();
13
13
  #subscription;
14
14
  #queryExecutor;
15
- #elementsClassNames;
15
+ #elementClassName;
16
16
  #componentId;
17
17
  #componentName;
18
- constructor(queryExecutor, elementsClassNames, componentId) {
19
- this.#componentId = componentId;
20
- this.#queryExecutor = queryExecutor;
21
- this.#elementsClassNames = elementsClassNames;
18
+ constructor(props) {
19
+ this.#componentId = props.componentId;
20
+ this.#queryExecutor = props.queryExecutor;
21
+ this.#elementClassName = props.elementClassName;
22
22
  this.#componentName = "ModelCategoryElementsCountCache";
23
23
  this.#subscription = this.#requestsStream
24
24
  .pipe(bufferTime(20), filter((requests) => requests.length > 0), mergeMap((requests) => this.queryCategoryElementCounts(requests)), mergeAll())
@@ -44,10 +44,11 @@ export class ModelCategoryElementsCountCache {
44
44
  // we may have thousands of where clauses here, and sending a single query with all of them could take a
45
45
  // long time - instead, split it into smaller chunks
46
46
  bufferCount(100), mergeMap((whereClauses) => defer(() => this.#queryExecutor.createQueryReader({
47
- ctes: this.#elementsClassNames.map((elementsClassName, index) => `
48
- CategoryElements${index}(id, modelId, categoryId) AS (
47
+ ctes: [
48
+ `
49
+ CategoryElements(id, modelId, categoryId) AS (
49
50
  SELECT ECInstanceId, Model.Id, Category.Id
50
- FROM ${elementsClassName}
51
+ FROM ${this.#elementClassName}
51
52
  WHERE
52
53
  Parent.Id IS NULL
53
54
  AND (
@@ -57,19 +58,14 @@ export class ModelCategoryElementsCountCache {
57
58
  UNION ALL
58
59
 
59
60
  SELECT c.ECInstanceId, p.modelId, p.categoryId
60
- FROM ${elementsClassName} c
61
- JOIN CategoryElements${index} p ON c.Parent.Id = p.id
61
+ FROM ${this.#elementClassName} c
62
+ JOIN CategoryElements p ON c.Parent.Id = p.id
62
63
  )
63
- `),
64
+ `,
65
+ ],
64
66
  ecsql: `
65
67
  SELECT modelId, categoryId, COUNT(id) elementsCount
66
- FROM (
67
- ${this.#elementsClassNames
68
- .map((_, index) => `
69
- SELECT * FROM CategoryElements${index}
70
- `)
71
- .join(" UNION ALL ")}
72
- )
68
+ FROM (SELECT * FROM CategoryElements)
73
69
  GROUP BY modelId, categoryId
74
70
  `,
75
71
  }, {
@@ -98,7 +94,7 @@ export class ModelCategoryElementsCountCache {
98
94
  [Symbol.dispose]() {
99
95
  this.#subscription.unsubscribe();
100
96
  }
101
- getCategoryElementsCount(modelId, categoryId) {
97
+ getCategoryElementsCount({ modelId, categoryId }) {
102
98
  const cacheKey = `${modelId}-${categoryId}`;
103
99
  let result = this.#cache.get(cacheKey);
104
100
  if (result !== undefined) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModelCategoryElementsCountCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/caches/ModelCategoryElementsCountCache.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 { bufferCount, bufferTime, defer, filter, from, map, mergeAll, mergeMap, reduce, ReplaySubject, Subject, take, toArray } from \"rxjs\";\nimport { assert, Guid } from \"@itwin/core-bentley\";\nimport { catchBeSQLiteInterrupts } from \"../UseErrorState.js\";\nimport { releaseMainThreadOnItemsCount } from \"../Utils.js\";\n\nimport type { Observable, Subscription } from \"rxjs\";\nimport type { GuidString, Id64Set, Id64String } from \"@itwin/core-bentley\";\nimport type { LimitingECSqlQueryExecutor } from \"@itwin/presentation-hierarchies\";\nimport type { CategoryId, ModelId } from \"../Types.js\";\n\ntype ModelCategoryKey = `${ModelId}-${CategoryId}`;\n\n/** @internal */\nexport class ModelCategoryElementsCountCache implements Disposable {\n #cache = new Map<ModelCategoryKey, Subject<number>>();\n #requestsStream = new Subject<{ modelId: Id64String; categoryId: Id64String }>();\n #subscription: Subscription;\n #queryExecutor: LimitingECSqlQueryExecutor;\n #elementClassName: string;\n #componentId: GuidString;\n #componentName: string;\n\n public constructor(props: { queryExecutor: LimitingECSqlQueryExecutor; elementClassName: string; componentId: GuidString }) {\n this.#componentId = props.componentId;\n this.#queryExecutor = props.queryExecutor;\n this.#elementClassName = props.elementClassName;\n this.#componentName = \"ModelCategoryElementsCountCache\";\n this.#subscription = this.#requestsStream\n .pipe(\n bufferTime(20),\n filter((requests) => requests.length > 0),\n mergeMap((requests) => this.queryCategoryElementCounts(requests)),\n mergeAll(),\n )\n .subscribe({\n next: ({ modelId, categoryId, elementsCount }) => {\n const subject = this.#cache.get(`${modelId}-${categoryId}`);\n assert(!!subject);\n subject.next(elementsCount);\n },\n });\n }\n\n private queryCategoryElementCounts(\n input: Array<{ modelId: Id64String; categoryId: Id64String }>,\n ): Observable<Array<{ modelId: Id64String; categoryId: Id64String; elementsCount: number }>> {\n return from(input).pipe(\n reduce((acc, { modelId, categoryId }) => {\n const entry = acc.get(modelId);\n if (!entry) {\n acc.set(modelId, new Set([categoryId]));\n } else {\n entry.add(categoryId);\n }\n return acc;\n }, new Map<Id64String, Id64Set>()),\n mergeMap((modelCategoryMap) => modelCategoryMap.entries()),\n map(([modelId, categoryIds]) => `Model.Id = ${modelId} AND Category.Id IN (${[...categoryIds].join(\", \")})`),\n // we may have thousands of where clauses here, and sending a single query with all of them could take a\n // long time - instead, split it into smaller chunks\n bufferCount(100),\n mergeMap((whereClauses) =>\n defer(() =>\n this.#queryExecutor.createQueryReader(\n {\n ctes: [\n `\n CategoryElements(id, modelId, categoryId) AS (\n SELECT ECInstanceId, Model.Id, Category.Id\n FROM ${this.#elementClassName}\n WHERE\n Parent.Id IS NULL\n AND (\n ${whereClauses.join(\" OR \")}\n )\n\n UNION ALL\n\n SELECT c.ECInstanceId, p.modelId, p.categoryId\n FROM ${this.#elementClassName} c\n JOIN CategoryElements p ON c.Parent.Id = p.id\n )\n `,\n ],\n ecsql: `\n SELECT modelId, categoryId, COUNT(id) elementsCount\n FROM (SELECT * FROM CategoryElements)\n GROUP BY modelId, categoryId\n `,\n },\n {\n rowFormat: \"ECSqlPropertyNames\",\n limit: \"unbounded\",\n restartToken: `${this.#componentName}/${this.#componentId}/category-element-counts/${Guid.createValue()}`,\n },\n ),\n ).pipe(catchBeSQLiteInterrupts),\n ),\n releaseMainThreadOnItemsCount(500),\n reduce(\n ({ acc, createKey }, row) => {\n acc.set(createKey({ modelId: row.modelId, categoryId: row.categoryId }), {\n modelId: row.modelId,\n categoryId: row.categoryId,\n elementsCount: row.elementsCount,\n });\n return { acc, createKey };\n },\n {\n acc: new Map<string, { modelId: Id64String; categoryId: Id64String; elementsCount: number }>(),\n createKey: (keyProps: { modelId: Id64String; categoryId: Id64String }) => `${keyProps.modelId}-${keyProps.categoryId}`,\n },\n ),\n mergeMap(({ acc: result, createKey }) => {\n input.forEach(({ modelId, categoryId }) => {\n if (!result.has(createKey({ modelId, categoryId }))) {\n result.set(createKey({ modelId, categoryId }), { categoryId, modelId, elementsCount: 0 });\n }\n });\n\n return from(result.values());\n }),\n toArray(),\n );\n }\n\n public [Symbol.dispose]() {\n this.#subscription.unsubscribe();\n }\n\n public getCategoryElementsCount({ modelId, categoryId }: { modelId: Id64String; categoryId: Id64String }): Observable<number> {\n const cacheKey: ModelCategoryKey = `${modelId}-${categoryId}`;\n let result = this.#cache.get(cacheKey);\n if (result !== undefined) {\n return from(result).pipe(take(1));\n }\n\n result = new ReplaySubject(1);\n this.#cache.set(cacheKey, result);\n this.#requestsStream.next({ modelId, categoryId });\n return from(result).pipe(take(1));\n }\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import type { Observable } from "rxjs";
2
+ import type { GuidString, Id64Array, Id64String } from "@itwin/core-bentley";
3
+ import type { LimitingECSqlQueryExecutor } from "@itwin/presentation-hierarchies";
4
+ import type { CategoryId, ElementId, ModelId } from "../Types.js";
5
+ interface ModeledElementsCacheProps {
6
+ queryExecutor: LimitingECSqlQueryExecutor;
7
+ componentId: GuidString;
8
+ elementClassName: string;
9
+ }
10
+ /** @internal */
11
+ export declare class ModeledElementsCache {
12
+ #private;
13
+ constructor(props: ModeledElementsCacheProps);
14
+ private queryModeledElements;
15
+ getModeledElementsInfo(): Observable<{
16
+ modelWithCategoryModeledElements: Map<ModelId, Map<CategoryId, Set<ElementId>>>;
17
+ allSubModels: Set<ElementId>;
18
+ childSubModels: Map<ElementId, Set<ElementId>>;
19
+ }>;
20
+ getSubModelsUnderElement(elementId: Id64String): Observable<Id64Array>;
21
+ getCategoryModeledElements({ modelId, categoryId }: {
22
+ modelId: Id64String;
23
+ categoryId: Id64String;
24
+ }): Observable<Id64String>;
25
+ }
26
+ export {};
27
+ //# sourceMappingURL=ModeledElementsCache.d.ts.map
@@ -0,0 +1,106 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { defer, map, mergeMap, reduce, shareReplay } from "rxjs";
6
+ import { CLASS_NAME_Model } from "../ClassNameDefinitions.js";
7
+ import { catchBeSQLiteInterrupts } from "../UseErrorState.js";
8
+ /** @internal */
9
+ export class ModeledElementsCache {
10
+ #queryExecutor;
11
+ #componentId;
12
+ #componentName;
13
+ #elementClassName;
14
+ // ElementId here is also a ModelId, since those elements are sub models.
15
+ #modeledElementsInfo;
16
+ constructor(props) {
17
+ this.#queryExecutor = props.queryExecutor;
18
+ this.#componentId = props.componentId;
19
+ this.#elementClassName = props.elementClassName;
20
+ this.#componentName = "ModeledElementsCache";
21
+ }
22
+ queryModeledElements() {
23
+ return defer(() => {
24
+ const query = `
25
+ SELECT
26
+ me.ECInstanceId modeledElementId,
27
+ me.Category.Id categoryId,
28
+ me.Model.Id modelId,
29
+ IIF(me.Parent.Id IS NULL,
30
+ '',
31
+ (
32
+ WITH RECURSIVE ModeledElementParents(parentId, parentPath) AS (
33
+ SELECT p.Parent.Id, CAST(IdToHex(p.ECInstanceId) AS TEXT)
34
+ FROM ${this.#elementClassName} p
35
+ WHERE p.ECInstanceId = me.Parent.Id
36
+ UNION ALL
37
+ SELECT pOfp.Parent.Id, CAST(IdToHex(pOfp.ECInstanceId) AS TEXT) || ';' || c.parentPath
38
+ FROM ${this.#elementClassName} pOfp
39
+ JOIN ModeledElementParents c ON c.parentId = pOfp.ECInstanceId
40
+ )
41
+ SELECT parentPath
42
+ FROM ModeledElementParents
43
+ WHERE parentId IS NULL
44
+ )
45
+ ) parentElements
46
+ FROM ${CLASS_NAME_Model} m
47
+ JOIN ${this.#elementClassName} me ON me.ECInstanceId = m.ModeledElement.Id
48
+ WHERE
49
+ m.IsPrivate = false
50
+ AND m.ECInstanceId IN (SELECT Model.Id FROM ${this.#elementClassName})
51
+ `;
52
+ return this.#queryExecutor.createQueryReader({ ecsql: query }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/modeled-elements` });
53
+ }).pipe(catchBeSQLiteInterrupts, map((row) => {
54
+ return { modelId: row.modelId, categoryId: row.categoryId, modeledElementId: row.modeledElementId, parentElements: row.parentElements.split(";") };
55
+ }));
56
+ }
57
+ getModeledElementsInfo() {
58
+ this.#modeledElementsInfo ??= this.queryModeledElements().pipe(reduce((acc, { modelId, categoryId, modeledElementId, parentElements }) => {
59
+ let modelEntry = acc.modelWithCategoryModeledElements.get(modelId);
60
+ if (!modelEntry) {
61
+ modelEntry = new Map();
62
+ acc.modelWithCategoryModeledElements.set(modelId, modelEntry);
63
+ }
64
+ const categoryEntry = modelEntry.get(categoryId);
65
+ if (!categoryEntry) {
66
+ modelEntry.set(categoryId, new Set([modeledElementId]));
67
+ }
68
+ else {
69
+ categoryEntry.add(modeledElementId);
70
+ }
71
+ acc.allSubModels.add(modeledElementId);
72
+ parentElements.forEach((parentElementId) => {
73
+ const entry = acc.childSubModels.get(parentElementId);
74
+ if (!entry) {
75
+ acc.childSubModels.set(parentElementId, new Set([modeledElementId]));
76
+ }
77
+ else {
78
+ entry.add(modeledElementId);
79
+ }
80
+ });
81
+ return acc;
82
+ }, {
83
+ modelWithCategoryModeledElements: new Map(),
84
+ allSubModels: new Set(),
85
+ childSubModels: new Map(),
86
+ }), shareReplay());
87
+ return this.#modeledElementsInfo;
88
+ }
89
+ getSubModelsUnderElement(elementId) {
90
+ return this.getModeledElementsInfo().pipe(map(({ allSubModels, childSubModels }) => {
91
+ const subModels = new Array();
92
+ if (allSubModels.has(elementId)) {
93
+ subModels.push(elementId);
94
+ }
95
+ const elementEntry = childSubModels.get(elementId);
96
+ for (const childSubModelId of elementEntry ?? []) {
97
+ subModels.push(childSubModelId);
98
+ }
99
+ return subModels;
100
+ }));
101
+ }
102
+ getCategoryModeledElements({ modelId, categoryId }) {
103
+ return this.getModeledElementsInfo().pipe(mergeMap(({ modelWithCategoryModeledElements }) => modelWithCategoryModeledElements.get(modelId)?.get(categoryId) ?? new Set()));
104
+ }
105
+ }
106
+ //# sourceMappingURL=ModeledElementsCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModeledElementsCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.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, map, mergeMap, reduce, shareReplay } from \"rxjs\";\nimport { CLASS_NAME_Model } from \"../ClassNameDefinitions.js\";\nimport { catchBeSQLiteInterrupts } from \"../UseErrorState.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { GuidString, Id64Array, Id64String } from \"@itwin/core-bentley\";\nimport type { LimitingECSqlQueryExecutor } from \"@itwin/presentation-hierarchies\";\nimport type { CategoryId, ElementId, ModelId } from \"../Types.js\";\n\ninterface ModeledElementsCacheProps {\n queryExecutor: LimitingECSqlQueryExecutor;\n componentId: GuidString;\n elementClassName: string;\n}\n\n/** @internal */\nexport class ModeledElementsCache {\n #queryExecutor: LimitingECSqlQueryExecutor;\n #componentId: GuidString;\n #componentName: string;\n #elementClassName: string;\n // ElementId here is also a ModelId, since those elements are sub models.\n #modeledElementsInfo:\n | Observable<{\n modelWithCategoryModeledElements: Map<ModelId, Map<CategoryId, Set<ElementId>>>;\n allSubModels: Set<ElementId>;\n childSubModels: Map<ElementId, Set<ElementId>>;\n }>\n | undefined;\n\n constructor(props: ModeledElementsCacheProps) {\n this.#queryExecutor = props.queryExecutor;\n this.#componentId = props.componentId;\n this.#elementClassName = props.elementClassName;\n this.#componentName = \"ModeledElementsCache\";\n }\n\n private queryModeledElements(): Observable<{\n modelId: Id64String;\n modeledElementId: Id64String;\n categoryId: Id64String;\n parentElements: Id64Array;\n }> {\n return defer(() => {\n const query = `\n SELECT\n me.ECInstanceId modeledElementId,\n me.Category.Id categoryId,\n me.Model.Id modelId,\n IIF(me.Parent.Id IS NULL,\n '',\n (\n WITH RECURSIVE ModeledElementParents(parentId, parentPath) AS (\n SELECT p.Parent.Id, CAST(IdToHex(p.ECInstanceId) AS TEXT)\n FROM ${this.#elementClassName} p\n WHERE p.ECInstanceId = me.Parent.Id\n UNION ALL\n SELECT pOfp.Parent.Id, CAST(IdToHex(pOfp.ECInstanceId) AS TEXT) || ';' || c.parentPath\n FROM ${this.#elementClassName} pOfp\n JOIN ModeledElementParents c ON c.parentId = pOfp.ECInstanceId\n )\n SELECT parentPath\n FROM ModeledElementParents\n WHERE parentId IS NULL\n )\n ) parentElements\n FROM ${CLASS_NAME_Model} m\n JOIN ${this.#elementClassName} me ON me.ECInstanceId = m.ModeledElement.Id\n WHERE\n m.IsPrivate = false\n AND m.ECInstanceId IN (SELECT Model.Id FROM ${this.#elementClassName})\n `;\n return this.#queryExecutor.createQueryReader(\n { ecsql: query },\n { rowFormat: \"ECSqlPropertyNames\", limit: \"unbounded\", restartToken: `${this.#componentName}/${this.#componentId}/modeled-elements` },\n );\n }).pipe(\n catchBeSQLiteInterrupts,\n map((row) => {\n return { modelId: row.modelId, categoryId: row.categoryId, modeledElementId: row.modeledElementId, parentElements: row.parentElements.split(\";\") };\n }),\n );\n }\n\n public getModeledElementsInfo() {\n this.#modeledElementsInfo ??= this.queryModeledElements().pipe(\n reduce(\n (acc, { modelId, categoryId, modeledElementId, parentElements }) => {\n let modelEntry = acc.modelWithCategoryModeledElements.get(modelId);\n if (!modelEntry) {\n modelEntry = new Map();\n acc.modelWithCategoryModeledElements.set(modelId, modelEntry);\n }\n const categoryEntry = modelEntry.get(categoryId);\n if (!categoryEntry) {\n modelEntry.set(categoryId, new Set([modeledElementId]));\n } else {\n categoryEntry.add(modeledElementId);\n }\n acc.allSubModels.add(modeledElementId);\n parentElements.forEach((parentElementId) => {\n const entry = acc.childSubModels.get(parentElementId);\n if (!entry) {\n acc.childSubModels.set(parentElementId, new Set([modeledElementId]));\n } else {\n entry.add(modeledElementId);\n }\n });\n return acc;\n },\n {\n modelWithCategoryModeledElements: new Map<ModelId, Map<CategoryId, Set<ElementId>>>(),\n allSubModels: new Set<ElementId>(),\n childSubModels: new Map<ElementId, Set<ElementId>>(),\n },\n ),\n shareReplay(),\n );\n return this.#modeledElementsInfo;\n }\n\n public getSubModelsUnderElement(elementId: Id64String): Observable<Id64Array> {\n return this.getModeledElementsInfo().pipe(\n map(({ allSubModels, childSubModels }) => {\n const subModels = new Array<ElementId>();\n if (allSubModels.has(elementId)) {\n subModels.push(elementId);\n }\n const elementEntry = childSubModels.get(elementId);\n for (const childSubModelId of elementEntry ?? []) {\n subModels.push(childSubModelId);\n }\n return subModels;\n }),\n );\n }\n\n public getCategoryModeledElements({ modelId, categoryId }: { modelId: Id64String; categoryId: Id64String }): Observable<Id64String> {\n return this.getModeledElementsInfo().pipe(\n mergeMap(({ modelWithCategoryModeledElements }) => modelWithCategoryModeledElements.get(modelId)?.get(categoryId) ?? new Set<Id64String>()),\n );\n }\n}\n"]}