UNPKG

@itwin/presentation-hierarchies

Version:

A package for creating hierarchies based on data in iTwin.js iModels.

162 lines 10.4 kB
"use strict"; /*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ Object.defineProperty(exports, "__esModule", { value: true }); exports.LOGGING_NAMESPACE = void 0; exports.createGroupingOperator = createGroupingOperator; const rxjs_1 = require("rxjs"); const core_bentley_1 = require("@itwin/core-bentley"); const HierarchyNode_js_1 = require("../../HierarchyNode.js"); const Common_js_1 = require("../../internal/Common.js"); const LoggingUtils_js_1 = require("../../internal/LoggingUtils.js"); const ReleaseMainThread_js_1 = require("../../internal/operators/ReleaseMainThread.js"); const TapOnce_js_1 = require("../../internal/operators/TapOnce.js"); const AutoExpand_js_1 = require("./grouping/AutoExpand.js"); const BaseClassGrouping_js_1 = require("./grouping/BaseClassGrouping.js"); const ClassGrouping_js_1 = require("./grouping/ClassGrouping.js"); const GroupHiding_js_1 = require("./grouping/GroupHiding.js"); const LabelGrouping_js_1 = require("./grouping/LabelGrouping.js"); const PropertiesGrouping_js_1 = require("./grouping/PropertiesGrouping.js"); const OPERATOR_NAME = "Grouping"; /** @internal */ exports.LOGGING_NAMESPACE = (0, Common_js_1.createOperatorLoggingNamespace)(OPERATOR_NAME, Common_js_1.LOGGING_NAMESPACE_INTERNAL); const LOGGING_NAMESPACE_PERFORMANCE = (0, Common_js_1.createOperatorLoggingNamespace)(OPERATOR_NAME, Common_js_1.LOGGING_NAMESPACE_PERFORMANCE); const LOGGING_NAMESPACE_PERFORMANCE_INTERNAL = (0, Common_js_1.createOperatorLoggingNamespace)(OPERATOR_NAME, Common_js_1.LOGGING_NAMESPACE_PERFORMANCE_INTERNAL); /** @internal */ function createGroupingOperator(imodelAccess, parentNode, valueFormatter, localizedStrings, onNodesGrouped, onGroupingNodeCreated, groupingHandlers) { return function (nodes) { return nodes.pipe((0, LoggingUtils_js_1.log)({ category: exports.LOGGING_NAMESPACE, message: /* c8 ignore next */ (n) => `in: ${(0, Common_js_1.createNodeIdentifierForLogging)(n)}` }), (0, TapOnce_js_1.tapOnce)(() => { (0, LoggingUtils_js_1.doLog)({ category: LOGGING_NAMESPACE_PERFORMANCE, message: /* c8 ignore next */ () => `Starting grouping (parent: ${(0, Common_js_1.createNodeIdentifierForLogging)(parentNode)})`, }); }), (0, rxjs_1.reduce)((resolvedNodes, node) => { if (HierarchyNode_js_1.HierarchyNode.isInstancesNode(node)) { resolvedNodes.instanceNodes.push(node); } else { resolvedNodes.restNodes.push(node); } return resolvedNodes; }, { instanceNodes: [], restNodes: [] }), (0, rxjs_1.tap)(({ instanceNodes, restNodes }) => { (0, LoggingUtils_js_1.doLog)({ category: LOGGING_NAMESPACE_PERFORMANCE_INTERNAL, message: /* c8 ignore next */ () => `Nodes partitioned. Got ${instanceNodes.length} instance nodes and ${restNodes.length} rest nodes.`, }); }), (0, rxjs_1.mergeMap)((res) => { const out = (0, rxjs_1.of)(res); const totalNodes = res.instanceNodes.length + res.restNodes.length; /* c8 ignore next */ return totalNodes <= 1000 ? out : out.pipe((0, rxjs_1.delay)(0)); }), (0, rxjs_1.mergeMap)(({ instanceNodes, restNodes }) => { const timer = new core_bentley_1.StopWatch(undefined, true); const groupingHandlersObs = groupingHandlers ? (0, rxjs_1.from)(groupingHandlers) : createGroupingHandlers(imodelAccess, parentNode, instanceNodes, valueFormatter, localizedStrings); return (0, rxjs_1.merge)(groupingHandlersObs.pipe((0, rxjs_1.toArray)(), (0, rxjs_1.mergeMap)((createdGroupingHandlers) => groupInstanceNodes(instanceNodes, restNodes.length, createdGroupingHandlers, parentNode, onNodesGrouped, onGroupingNodeCreated)), (0, rxjs_1.finalize)(() => { (0, LoggingUtils_js_1.doLog)({ category: LOGGING_NAMESPACE_PERFORMANCE, message: /* c8 ignore next */ () => `Grouping ${instanceNodes.length} nodes took ${timer.elapsedSeconds.toFixed(3)} s`, }); })), (0, rxjs_1.from)(restNodes)); }), (0, ReleaseMainThread_js_1.releaseMainThreadOnItemsCount)(500), (0, LoggingUtils_js_1.log)({ category: exports.LOGGING_NAMESPACE, message: /* c8 ignore next */ (n) => `out: ${(0, Common_js_1.createNodeIdentifierForLogging)(n)}` })); }; } function groupInstanceNodes(nodes, extraSiblings, groupingHandlers, parentNode, onNodesGrouped, onGroupingNodeCreated) { if (groupingHandlers.length === 0) { return (0, rxjs_1.from)(nodes); } return (0, rxjs_1.of)({ handlerIndex: 0 }).pipe((0, rxjs_1.expand)(({ handlerIndex, result: curr }) => { if (handlerIndex >= groupingHandlers.length) { return rxjs_1.EMPTY; } const timer = new core_bentley_1.StopWatch(undefined, true); const currentHandler = groupingHandlers[handlerIndex]; return (0, rxjs_1.from)(currentHandler(curr?.ungrouped ?? nodes, curr?.grouped ?? [])).pipe((0, LoggingUtils_js_1.log)({ category: LOGGING_NAMESPACE_PERFORMANCE_INTERNAL, message: /* c8 ignore next */ () => `Grouping handler ${handlerIndex} exclusively took ${timer.elapsedSeconds.toFixed(3)} s.`, }), (0, rxjs_1.tap)((result) => { onNodesGrouped?.(result, currentHandler); }), (0, rxjs_1.mergeMap)((result) => { if (result.grouped.length === 0) { return (0, rxjs_1.of)({ handlerIndex: handlerIndex + 1, result: { ...result, grouped: curr?.grouped ?? [] } }); } const groupingPostProcessingTimer = new core_bentley_1.StopWatch(undefined, true); return (0, rxjs_1.of)(result).pipe((0, rxjs_1.map)((r) => (0, GroupHiding_js_1.applyGroupHidingParams)(r, extraSiblings)), (0, rxjs_1.map)((r) => (0, AutoExpand_js_1.assignAutoExpand)(r)), (0, rxjs_1.map)((r) => ({ handlerIndex: handlerIndex + 1, result: { ...r, grouped: mergeInPlace(curr?.grouped, r.grouped) } })), (0, LoggingUtils_js_1.log)({ category: LOGGING_NAMESPACE_PERFORMANCE_INTERNAL, message: /* c8 ignore next */ () => `Post-processing grouping handler ${handlerIndex} exclusively took ${groupingPostProcessingTimer.elapsedSeconds.toFixed(3)} s.`, }), (0, rxjs_1.delay)(0)); }), (0, LoggingUtils_js_1.log)({ category: LOGGING_NAMESPACE_PERFORMANCE_INTERNAL, message: /* c8 ignore next */ () => `Total time for grouping handler ${handlerIndex}: ${timer.elapsedSeconds.toFixed(3)} s.`, })); }), (0, rxjs_1.last)(), (0, rxjs_1.mergeMap)(({ result }) => { result.grouped.forEach((groupingNode) => { onGroupingNodeCreated?.(groupingNode); if (!parentNode) { return; } if (HierarchyNode_js_1.HierarchyNode.isGroupingNode(parentNode)) { groupingNode.nonGroupingAncestor = parentNode.nonGroupingAncestor; return; } // not sure why type checker doesn't pick this up (0, core_bentley_1.assert)(HierarchyNode_js_1.HierarchyNode.isGeneric(parentNode) || HierarchyNode_js_1.HierarchyNode.isInstancesNode(parentNode)); groupingNode.nonGroupingAncestor = parentNode; }); return mergeInPlace(result.grouped, result.ungrouped); })); } function mergeInPlace(target, source) { if (!target || target.length === 0) { return source; } for (const item of source) { target.push(item); } return target; } function createGroupingHandlers(imodelAccess, parentNode, processedInstanceNodes, valueFormatter, localizedStrings) { const timer = new core_bentley_1.StopWatch(); const groupingLevel = getNodeGroupingLevel(parentNode); return (0, rxjs_1.concat)(groupingLevel <= GroupingLevel.Class ? (0, rxjs_1.concat)((0, rxjs_1.from)((0, BaseClassGrouping_js_1.createBaseClassGroupingHandlers)(imodelAccess, parentNode, processedInstanceNodes)).pipe((0, rxjs_1.concatAll)()), (0, rxjs_1.of)(async (allNodes) => (0, ClassGrouping_js_1.createClassGroups)(imodelAccess, parentNode, allNodes))) : rxjs_1.EMPTY, groupingLevel <= GroupingLevel.Property ? (0, rxjs_1.from)((0, PropertiesGrouping_js_1.createPropertiesGroupingHandlers)(imodelAccess, parentNode, processedInstanceNodes, valueFormatter, localizedStrings)).pipe((0, rxjs_1.concatAll)()) : rxjs_1.EMPTY, groupingLevel < GroupingLevel.Label ? (0, rxjs_1.of)(async (allNodes) => (0, LabelGrouping_js_1.createLabelGroups)(allNodes)) : rxjs_1.EMPTY).pipe((0, rxjs_1.tap)({ subscribe: () => { (0, LoggingUtils_js_1.doLog)({ category: LOGGING_NAMESPACE_PERFORMANCE_INTERNAL, message: /* c8 ignore next */ () => `Start creating grouping handlers`, }); timer.start(); }, }), (0, rxjs_1.finalize)(() => { (0, LoggingUtils_js_1.doLog)({ category: LOGGING_NAMESPACE_PERFORMANCE_INTERNAL, message: /* c8 ignore next */ () => `Creating grouping handlers took ${timer.elapsedSeconds.toFixed(3)} s`, }); })); } function getNodeGroupingLevel(node) { if (node && HierarchyNode_js_1.HierarchyNode.isClassGroupingNode(node)) { return GroupingLevel.Class; } if (node && HierarchyNode_js_1.HierarchyNode.isPropertyGroupingNode(node)) { return GroupingLevel.Property; } if (node && HierarchyNode_js_1.HierarchyNode.isLabelGroupingNode(node)) { return GroupingLevel.Label; } return GroupingLevel.None; } var GroupingLevel; (function (GroupingLevel) { GroupingLevel[GroupingLevel["None"] = 0] = "None"; GroupingLevel[GroupingLevel["Class"] = 2] = "Class"; GroupingLevel[GroupingLevel["Property"] = 3] = "Property"; GroupingLevel[GroupingLevel["Label"] = 4] = "Label"; })(GroupingLevel || (GroupingLevel = {})); //# sourceMappingURL=Grouping.js.map