@itwin/presentation-components
Version:
React components based on iTwin.js Presentation library
156 lines • 6.84 kB
JavaScript
;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module InstancesFilter
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.findBaseExpressionClassName = findBaseExpressionClassName;
exports.createInstanceFilterDefinitionBase = createInstanceFilterDefinitionBase;
exports.createFilterExpression = createFilterExpression;
exports.createFilterClassExpression = createFilterClassExpression;
const appui_abstract_1 = require("@itwin/appui-abstract");
const components_react_1 = require("@itwin/components-react");
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const ECMetadataProvider_js_1 = require("./ECMetadataProvider.js");
const PresentationInstanceFilter_js_1 = require("./PresentationInstanceFilter.js");
/** @internal */
async function findBaseExpressionClassName(imodel, propertyClassNames) {
if (propertyClassNames.length === 1) {
return propertyClassNames[0];
}
const metadataProvider = (0, ECMetadataProvider_js_1.getIModelMetadataProvider)(imodel);
const [firstClassName, ...restClassNames] = propertyClassNames;
let currentBaseClassInfo = await metadataProvider.getECClassInfo(firstClassName);
/* c8 ignore next 3 */
if (!currentBaseClassInfo) {
return firstClassName;
}
for (const propClassName of restClassNames) {
const propClassInfo = await metadataProvider.getECClassInfo(propClassName);
if (propClassInfo && propClassInfo.isDerivedFrom(currentBaseClassInfo.id)) {
currentBaseClassInfo = propClassInfo;
}
}
return currentBaseClassInfo.name;
}
/** @internal */
async function createInstanceFilterDefinitionBase(filter, imodel) {
const { rules, propertyClassNames, relatedInstances } = PresentationInstanceFilter_js_1.PresentationInstanceFilter.toGenericInstanceFilter(filter);
const filterExpression = createFilterExpression(rules);
const baseClassName = await findBaseExpressionClassName(imodel, propertyClassNames);
return {
expression: filterExpression,
selectClassName: baseClassName,
relatedInstances: relatedInstances.map((related) => ({
pathFromSelectToPropertyClass: related.path.map((step) => ({
sourceClassName: step.sourceClassName,
targetClassName: step.targetClassName,
relationshipName: step.relationshipClassName,
isForwardRelationship: step.isForwardRelationship,
})),
alias: related.alias,
})),
};
}
/** @internal */
function createFilterExpression(filter) {
return createComparisonExpression(filter);
}
function createComparisonExpression(filter) {
if (core_common_1.GenericInstanceFilter.isFilterRuleGroup(filter)) {
return createExpressionFromGroup(filter);
}
const { propertyName, propertyTypeName, sourceAlias, operator, value } = filter;
return createComparison(propertyName, propertyTypeName, sourceAlias, operator, value);
}
function createExpressionFromGroup(group) {
const convertedConditions = group.rules.map((rule) => createComparisonExpression(rule));
return `(${convertedConditions.join(` ${getGroupOperatorString(group.operator)} `)})`;
}
/** @internal */
function createFilterClassExpression(usedClasses) {
if (usedClasses.length === 0) {
return "";
}
return `(${usedClasses.map((classInfo) => `this.IsOfClass(${classInfo.id})`).join(" OR ")})`;
}
function createComparison(propertyName, type, alias, operator, propValue) {
const propertyAccessor = `${alias}.${propertyName}`;
const operatorExpression = getRuleOperatorString(operator);
if (propValue === undefined || (0, components_react_1.isUnaryPropertyFilterOperator)(operator)) {
return `${propertyAccessor} ${operatorExpression}`;
}
const value = propValue.rawValue;
if (operator === "like" && typeof value === "string") {
return `${propertyAccessor} ${operatorExpression} "%${escapeString(value)}%"`;
}
let valueExpression = "";
switch (typeof value) {
case "string":
valueExpression = `"${escapeString(value)}"`;
break;
case "number":
valueExpression = value.toString();
break;
}
if (type === appui_abstract_1.StandardTypeNames.Point2d || type === appui_abstract_1.StandardTypeNames.Point3d) {
(0, core_bentley_1.assert)(core_common_1.GenericInstanceFilterRuleValue.isPoint2d(value));
return createPointComparison(value, operatorExpression, propertyAccessor);
}
if (type === "navigation") {
return `${propertyAccessor}.Id ${operatorExpression} ${value.id}`;
}
if (type === "double") {
return `CompareDoubles(${propertyAccessor}, ${valueExpression}) ${operatorExpression} 0`;
}
if (type === "dateTime") {
return `CompareDateTimes(${propertyAccessor}, ${valueExpression}) ${operatorExpression} 0`;
}
return `${propertyAccessor} ${operatorExpression} ${valueExpression}`;
}
function getGroupOperatorString(operator) {
switch (operator) {
case "and":
return "AND";
case "or":
return "OR";
}
}
function getRuleOperatorString(operator) {
switch (operator) {
case "is-true":
return "= TRUE";
case "is-false":
return "= FALSE";
case "is-equal":
return "=";
case "is-not-equal":
return "<>";
case "greater":
return ">";
case "greater-or-equal":
return ">=";
case "less":
return "<";
case "less-or-equal":
return "<=";
case "like":
return "~";
case "is-null":
return "= NULL";
case "is-not-null":
return "<> NULL";
}
}
function escapeString(str) {
return str.replace(/"/g, `""`);
}
function createPointComparison(point, operatorExpression, propertyAccessor) {
const logicalOperator = operatorExpression === "=" ? "AND" : "OR";
return `(CompareDoubles(${propertyAccessor}.x, ${point.x}) ${operatorExpression} 0) ${logicalOperator} (CompareDoubles(${propertyAccessor}.y, ${point.y}) ${operatorExpression} 0)${core_common_1.GenericInstanceFilterRuleValue.isPoint3d(point) ? ` ${logicalOperator} (CompareDoubles(${propertyAccessor}.z, ${point.z}) ${operatorExpression} 0)` : ""}`;
}
//# sourceMappingURL=InstanceFilterConverter.js.map