UNPKG

@itwin/unified-selection

Version:

Package for managing unified selection in iTwin.js applications.

217 lines 9.58 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.computeSelection = computeSelection; const core_bentley_1 = require("@itwin/core-bentley"); const Utils_js_1 = require("./Utils.js"); /** * Computes selection from given element IDs. * @public */ async function* computeSelection(props) { const { queryExecutor, elementIds, scope } = props; const componentId = props.componentId ?? core_bentley_1.Guid.createValue(); const componentName = "computeSelection"; if (typeof scope === "string") { yield* computeSelection({ queryExecutor, elementIds, scope: { id: scope }, componentId }); return; } const nonTransientIds = []; for (const id of core_bentley_1.Id64.iterable(elementIds)) { if (!core_bentley_1.Id64.isTransient(id)) { nonTransientIds.push(id); } } switch (scope.id) { case "element": yield* computeElementSelection(queryExecutor, nonTransientIds, scope.ancestorLevel ?? 0, componentId, componentName); return; case "category": yield* computeCategorySelection(queryExecutor, nonTransientIds, componentId, componentName); return; case "model": yield* computeModelSelection(queryExecutor, nonTransientIds, componentId, componentName); return; case "functional": yield* computeFunctionalElementSelection(queryExecutor, nonTransientIds, scope.ancestorLevel ?? 0, componentId, componentName); return; } } async function* computeElementSelection(queryExecutor, elementIds, ancestorLevel, componentId, componentName) { const bindings = []; const recurseUntilRoot = ancestorLevel < 0; const ctes = [ ` AncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS ( SELECT ECInstanceId, ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, Parent.Id FROM BisCore.Element WHERE ${(0, Utils_js_1.formIdBindings)("ECInstanceId", elementIds, bindings)} UNION ALL SELECT pe.ECInstanceId, pe.ECClassId, a.Depth - 1, pe.Parent.Id FROM AncestorElements a JOIN BisCore.Element pe ON pe.ECInstanceId = a.ParentId WHERE ${recurseUntilRoot ? "" : "Depth > 0 AND"} ParentId IS NOT NULL ) `, ]; const ecsql = ` SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName FROM AncestorElements WHERE ${recurseUntilRoot ? "" : "Depth = 0 OR"} ParentId IS NULL `; yield* executeQuery({ queryExecutor, query: { ctes, ecsql, bindings }, config: { restartToken: `${componentName}/${componentId}/element/${core_bentley_1.Guid.createValue()}` }, }); } async function* computeCategorySelection(queryExecutor, ids, componentId, componentName) { const bindings = []; const ecsql = [ ` SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName FROM BisCore.Category c JOIN BisCore.GeometricElement2d ge ON ge.Category.Id = c.ECInstanceId WHERE ${(0, Utils_js_1.formIdBindings)("ge.ECInstanceId", ids, bindings)} `, ` SELECT DISTINCT c.ECInstanceId, ec_classname(c.ECClassId, 's.c') AS ClassName FROM BisCore.Category c JOIN BisCore.GeometricElement3d ge ON ge.Category.Id = c.ECInstanceId WHERE ${(0, Utils_js_1.formIdBindings)("ge.ECInstanceId", ids, bindings)} `, ].join(" UNION ALL "); yield* executeQuery({ queryExecutor, query: { ecsql, bindings }, config: { restartToken: `${componentName}/${componentId}/category/${core_bentley_1.Guid.createValue()}` }, }); } async function* computeModelSelection(queryExecutor, ids, componentId, componentName) { const bindings = []; const ecsql = ` SELECT DISTINCT m.ECInstanceId, ec_classname(m.ECClassId, 's.c') AS ClassName FROM BisCore.Model m JOIN BisCore.Element e ON e.Model.Id = m.ECInstanceId WHERE ${(0, Utils_js_1.formIdBindings)("e.ECInstanceId", ids, bindings)} `; yield* executeQuery({ queryExecutor, query: { ecsql, bindings }, config: { restartToken: `${componentName}/${componentId}/model/${core_bentley_1.Guid.createValue()}` }, }); } async function* computeFunctionalElementSelection(queryExecutor, ids, ancestorLevel, componentId, componentName) { const bindings = []; const recurseUntilRoot = ancestorLevel < 0; // cspell:disable const ctes = [ ` Elements2dOrNearestFunctionalElements(OriginalECInstanceId, OriginalECClassId, ECInstanceId, ECClassId, ParentId) AS ( SELECT ECInstanceId, ECClassId, ECInstanceId, ECClassId, Parent.Id FROM BisCore.Element WHERE ${(0, Utils_js_1.formIdBindings)("ECInstanceId", ids, bindings)} AND ECClassId IS NOT (BisCore.GeometricElement3d) UNION ALL SELECT e2onfe.OriginalECInstanceId, e2onfe.OriginalECClassId, COALESCE(dgrfe.TargetECInstanceId, pe.ECInstanceId), COALESCE(dgrfe.TargetECClassId, pe.ECClassId), pe.Parent.Id FROM Elements2dOrNearestFunctionalElements e2onfe LEFT JOIN BisCore.Element pe ON pe.ECInstanceId = e2onfe.ParentId LEFT JOIN Functional.DrawingGraphicRepresentsFunctionalElement dgrfe ON dgrfe.SourceECInstanceId = e2onfe.ECInstanceId WHERE e2onfe.ECClassId IS NOT (Functional.FunctionalElement) AND (e2onfe.ParentId IS NOT NULL OR dgrfe.TargetECInstanceId IS NOT NULL) ) `, ` Element2dNearestFunctionalElements(OriginalECInstanceId, ECInstanceId, ECClassId) AS ( SELECT OriginalECInstanceId, ECInstanceId, ECClassId FROM Elements2dOrNearestFunctionalElements WHERE ECClassId IS (Functional.FunctionalElement) ) `, ` Elements2dWithoutFunctionalElement(ECInstanceId, ECClassId) AS ( SELECT e2wfe.OriginalECInstanceId, OriginalECClassId FROM Elements2dOrNearestFunctionalElements e2wfe LEFT JOIN Element2dNearestFunctionalElements e2nfe ON e2nfe.OriginalECInstanceId = e2wfe.OriginalECInstanceId WHERE e2wfe.ParentId IS NULL AND e2nfe.ECInstanceId IS NULL ) `, ` Elements2d(ECInstanceId, ECClassId) AS ( SELECT ECInstanceId, ECClassId FROM Element2dNearestFunctionalElements UNION SELECT ECInstanceId, ECClassId FROM Elements2dWithoutFunctionalElement ) `, ` Element2dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS ( SELECT e.ECInstanceId, e.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, e.Parent.Id FROM BisCore.Element e JOIN Elements2d e2d ON e2d.ECInstanceId = e.ECInstanceId UNION ALL SELECT pe.ECInstanceId, pe.ECClassId, e2ae.Depth - 1, pe.Parent.Id FROM Element2dAncestorElements e2ae JOIN BisCore.Element pe ON pe.ECInstanceId = e2ae.ParentId WHERE ${recurseUntilRoot ? "" : "Depth > 0 AND"} ParentId IS NOT NULL ) `, ` Element3dAncestorElements(ECInstanceId, ECClassId, Depth, ParentId) AS ( SELECT ge.ECInstanceId, ge.ECClassId, ${formAncestorLevelBinding(ancestorLevel, bindings)}, ge.Parent.Id FROM BisCore.GeometricElement3d ge WHERE ${(0, Utils_js_1.formIdBindings)("ge.ECInstanceId", ids, bindings)} UNION ALL SELECT pe.ECInstanceId, pe.ECClassId, e3ae.Depth - 1, pe.Parent.Id FROM Element3dAncestorElements e3ae JOIN BisCore.Element pe ON pe.ECInstanceId = e3ae.ParentId WHERE ${recurseUntilRoot ? "" : "Depth > 0 AND"} ParentId IS NOT NULL ) `, ` Element3dAncestorRelatedFunctionalElement(ECInstanceId, ClassName) AS ( SELECT COALESCE(peff.TargetECInstanceId, e3ae.ECInstanceId), ec_classname(COALESCE(peff.TargetECClassId, e3ae.ECClassId), 's.c') FROM Element3dAncestorElements e3ae LEFT JOIN Functional.PhysicalElementFulfillsFunction peff ON peff.SourceECInstanceId = e3ae.ECInstanceId WHERE ${recurseUntilRoot ? "" : "e3ae.Depth = 0 OR"} e3ae.ParentId IS NULL ) `, ]; const ecsql = [ ` SELECT DISTINCT ECInstanceId, ec_classname(ECClassId, 's.c') AS ClassName FROM Element2dAncestorElements WHERE ${recurseUntilRoot ? "" : "Depth = 0 OR"} ParentId IS NULL `, ` SELECT DISTINCT ECInstanceId, ClassName FROM Element3dAncestorRelatedFunctionalElement `, ].join(" UNION "); // cspell:enable yield* executeQuery({ queryExecutor, query: { ctes, ecsql, bindings }, config: { restartToken: `${componentName}/${componentId}/functional-element/${core_bentley_1.Guid.createValue()}` }, }); } function formAncestorLevelBinding(ancestorLevel, bindings) { bindings.push({ type: "int", value: ancestorLevel }); return "?"; } async function* executeQuery(props) { yield* (0, Utils_js_1.genericExecuteQuery)({ ...props, parseQueryRow: (row) => ({ className: row.ClassName, id: row.ECInstanceId, }), }); } //# sourceMappingURL=SelectionScope.js.map