UNPKG

@itwin/presentation-hierarchies

Version:

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

90 lines 4.33 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { concatMap, filter, firstValueFrom, from, mergeAll, mergeMap, toArray } from "rxjs"; import { HierarchyNode } from "../HierarchyNode.js"; /** * Creates an instance of `HierarchyDefinition` that uses a somewhat declarative approach to define the * hierarchy - each hierarchy level is defined by specifying a parent node predicate and child hierarchy * level definitions, that are used when the predicate passes. * * @public */ export function createPredicateBasedHierarchyDefinition(props) { return new PredicateBasedHierarchyDefinition(props); } class PredicateBasedHierarchyDefinition { _props; parseNode; preProcessNode; postProcessNode; constructor(_props) { this._props = _props; if (this._props.parseNode) { this.parseNode = this._props.parseNode; } if (this._props.preProcessNode) { this.preProcessNode = this._props.preProcessNode; } if (this._props.postProcessNode) { this.postProcessNode = this._props.postProcessNode; } } /** * Create hierarchy level definitions for specific hierarchy level. * @param parentNode Parent node to create children definitions for. */ async defineHierarchyLevel(props) { const { parentNode } = props; if (parentNode && HierarchyNode.isGeneric(parentNode)) { return firstValueFrom(from(this._props.hierarchy.childNodes).pipe(filter(isGenericNodeChildHierarchyLevelDefinition), mergeMap(async (def) => { if (await def.parentGenericNodePredicate(parentNode.key)) { return def.definitions({ ...props, parentNode }); } return []; }), mergeAll(), toArray())); } if (parentNode && HierarchyNode.isInstancesNode(parentNode)) { const instancesParentNodeDefs = this._props.hierarchy.childNodes.filter(isInstancesNodeChildHierarchyLevelDefinition); return firstValueFrom(from(groupInstanceIdsByClass(parentNode.key.instanceKeys).entries()).pipe(mergeMap(async ([parentNodeClassName, parentNodeInstanceIds]) => createHierarchyLevelDefinitions(this._props.classHierarchyInspector, instancesParentNodeDefs, { ...props, parentNodeClassName, parentNodeInstanceIds, parentNode, })), mergeAll(), toArray())); } return this._props.hierarchy.rootNodes(props); } } async function createHierarchyLevelDefinitions(classHierarchy, defs, requestProps) { return from(defs).pipe(mergeMap(async (def, idx) => { if (typeof def.parentInstancesNodePredicate === "string" && (await classHierarchy.classDerivesFrom(requestProps.parentNodeClassName, def.parentInstancesNodePredicate))) { return { def, idx }; } if (typeof def.parentInstancesNodePredicate === "function" && (await def.parentInstancesNodePredicate(requestProps.parentNode.key))) { return { def, idx }; } return undefined; }), filter((x) => !!x), toArray(), concatMap((x) => x.sort((a, b) => a.idx - b.idx).map(({ def }) => def)), filter((def, idx) => !def.onlyIfNotHandled || idx === 0), mergeMap(async (def) => def.definitions(requestProps)), mergeAll()); } function groupInstanceIdsByClass(instanceKeys) { const instanceIdsByClass = new Map(); instanceKeys.forEach((key) => { let instanceIds = instanceIdsByClass.get(key.className); if (!instanceIds) { instanceIds = []; instanceIdsByClass.set(key.className, instanceIds); } instanceIds.push(key.id); }); return instanceIdsByClass; } function isGenericNodeChildHierarchyLevelDefinition(def) { return !!def.parentGenericNodePredicate; } function isInstancesNodeChildHierarchyLevelDefinition(def) { return !!def.parentInstancesNodePredicate; } //# sourceMappingURL=PredicateBasedHierarchyDefinition.js.map