UNPKG

@itwin/core-backend

Version:
250 lines • 10.8 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.createUpdateContext = createUpdateContext; exports.updateField = updateField; exports.updateFields = updateFields; exports.updateElementFields = updateElementFields; exports.updateAllFields = updateAllFields; const core_common_1 = require("@itwin/core-common"); const core_bentley_1 = require("@itwin/core-bentley"); const BackendLoggerCategory_1 = require("../../BackendLoggerCategory"); const ElementDrivesTextAnnotation_1 = require("../../annotations/ElementDrivesTextAnnotation"); const ecschema_metadata_1 = require("@itwin/ecschema-metadata"); // Resolve the raw primitive value of the property that a field points to. function getFieldPropertyValue(field, iModel) { const host = field.propertyHost; const schemaItem = iModel.schemaContext.getSchemaItemSync(host.schemaName, host.className); if (!ecschema_metadata_1.EntityClass.isEntityClass(schemaItem)) { return undefined; } let ecClass = schemaItem; const { propertyName, accessors } = field.propertyPath; let ecProp = ecClass.getPropertySync(propertyName); if (!ecProp) { return undefined; } const isAspect = ecClass.isSync("ElementAspect", "BisCore"); const where = ` WHERE ${isAspect ? "Element.Id" : "ECInstanceId"}=${host.elementId}`; // eslint-disable-next-line @typescript-eslint/no-deprecated let curValue = iModel.withPreparedStatement(`SELECT ${propertyName} FROM ${host.schemaName}.${host.className} ${where}`, (stmt) => { if (stmt.step() !== core_bentley_1.DbResult.BE_SQLITE_ROW) { return undefined; } const rootValue = stmt.getValue(0); if (undefined === rootValue || rootValue.isNull) { return undefined; } switch (rootValue.columnInfo.getType()) { case core_common_1.ECSqlValueType.Blob: return { primitive: rootValue.getBlob() }; case core_common_1.ECSqlValueType.Boolean: return { primitive: rootValue.getBoolean() }; case core_common_1.ECSqlValueType.DateTime: return { primitive: new Date(rootValue.getDateTime()) }; case core_common_1.ECSqlValueType.Double: return { primitive: rootValue.getDouble() }; case core_common_1.ECSqlValueType.Guid: return { primitive: rootValue.getGuid() }; case core_common_1.ECSqlValueType.Int: case core_common_1.ECSqlValueType.Int64: return { primitive: rootValue.getInteger() }; case core_common_1.ECSqlValueType.Point2d: return { primitive: rootValue.getXAndY() }; case core_common_1.ECSqlValueType.Point3d: return { primitive: rootValue.getXYAndZ() }; case core_common_1.ECSqlValueType.String: return { primitive: rootValue.getString() }; case core_common_1.ECSqlValueType.Struct: { ecProp = (0, core_bentley_1.expectDefined)(ecProp); (0, core_bentley_1.assert)(ecProp.isStruct()); ecClass = ecProp.structClass; return { struct: rootValue.getStruct() }; } case core_common_1.ECSqlValueType.PrimitiveArray: { return { primitiveArray: rootValue.getArray() }; } case core_common_1.ECSqlValueType.StructArray: { return { structArray: rootValue.getArray() }; } // Unsupported: // case ECSqlValueType.Geometry: // case ECSqlValueType.Navigation: // case ECSqlValueType.Id: } return undefined; }); if (undefined === curValue) { return undefined; } if (accessors) { for (const accessor of accessors) { if (undefined !== curValue.primitive) { // Can't index into a primitive. return undefined; } if (typeof accessor === "number") { const array = curValue.primitiveArray ?? curValue.structArray; if (!array) { return undefined; } const index = accessor < 0 ? (array.length + accessor) : accessor; const item = array[index]; if (undefined === item) { return undefined; } else if (curValue.primitiveArray) { curValue = { primitive: curValue.primitiveArray[index] }; } else { (0, core_bentley_1.assert)(undefined !== curValue.structArray); (0, core_bentley_1.assert)(ecProp instanceof ecschema_metadata_1.StructArrayProperty); ecClass = ecProp.structClass; curValue = { struct: curValue.structArray[index] }; } } else { if (undefined === curValue.struct) { return undefined; } const item = curValue.struct[accessor]; if (undefined === item) { return undefined; } ecProp = ecClass.getPropertySync(accessor); if (!ecProp) { return undefined; } if (ecProp.isArray()) { curValue = ecProp.isStruct() ? { structArray: item } : { primitiveArray: item }; } else if (ecProp.isStruct()) { ecClass = ecProp.structClass; curValue = { struct: item }; } else if (ecProp.isPrimitive()) { curValue = { primitive: item }; } else { return undefined; } } } } const propertyType = determineFieldPropertyType(ecProp); if (!propertyType) { return undefined; } // The ultimate result must be a primitive value. if (undefined === curValue.primitive) { return undefined; } return { value: curValue.primitive, type: propertyType }; } function determineFieldPropertyType(prop) { if (prop.isEnumeration()) { switch (prop.propertyType) { case ecschema_metadata_1.PropertyType.Integer_Enumeration: return "int-enum"; case ecschema_metadata_1.PropertyType.String_Enumeration: return "string-enum"; default: return undefined; } } if (prop.isPrimitive()) { switch (prop.primitiveType) { case ecschema_metadata_1.PrimitiveType.Boolean: return "boolean"; case ecschema_metadata_1.PrimitiveType.String: return prop.extendedTypeName === "DateTime" ? "datetime" : "string"; case ecschema_metadata_1.PrimitiveType.DateTime: return "datetime"; case ecschema_metadata_1.PrimitiveType.Double: case ecschema_metadata_1.PrimitiveType.Long: return "quantity"; case ecschema_metadata_1.PrimitiveType.Point2d: case ecschema_metadata_1.PrimitiveType.Point3d: return "coordinate"; case ecschema_metadata_1.PrimitiveType.Binary: return prop.extendedTypeName === "BeGuid" ? "string" : undefined; case ecschema_metadata_1.PrimitiveType.Integer: case ecschema_metadata_1.PrimitiveType.Long: return "string"; default: return undefined; } } return undefined; } function createUpdateContext(hostElementId, iModel, deleted) { return { hostElementId, getProperty: deleted ? () => undefined : (field) => getFieldPropertyValue(field, iModel), }; } // Recompute the display value of a single field, return false if it couldn't be evaluated. function updateField(field, context) { if (context.hostElementId && context.hostElementId !== field.propertyHost.elementId) { return false; } let newContent; try { const propValue = context.getProperty(field); if (undefined !== propValue) { newContent = (0, core_common_1.formatFieldValue)(propValue, field.formatOptions); } } catch (err) { core_bentley_1.Logger.logException(BackendLoggerCategory_1.BackendLoggerCategory.IModelDb, err); } newContent = newContent ?? core_common_1.FieldRun.invalidContentIndicator; if (newContent === field.cachedContent) { return false; } field.setCachedContent(newContent); return true; } // Re-evaluates the display strings for all fields that target the element specified by `context` and returns the number // of fields whose display strings changed as a result. function updateFields(textBlock, context) { let numUpdated = 0; for (const { child } of (0, core_common_1.traverseTextBlockComponent)(textBlock)) { if (child.type === "field" && updateField(child, context)) { ++numUpdated; } } return numUpdated; } function doUpdateFields(annotationId, sourceId, iModel, deleted) { try { const target = iModel.elements.getElement(annotationId); if ((0, ElementDrivesTextAnnotation_1.isITextAnnotation)(target)) { const context = createUpdateContext(sourceId, iModel, deleted); const updatedBlocks = []; for (const block of target.getTextBlocks()) { if (updateFields(block.textBlock, context)) { updatedBlocks.push(block); } } if (updatedBlocks.length > 0) { target.updateTextBlocks(updatedBlocks); target.update(); } } } catch (err) { core_bentley_1.Logger.logException(BackendLoggerCategory_1.BackendLoggerCategory.IModelDb, err); } } // Invoked by ElementDrivesTextAnnotation to update fields in target element when source element changes or is deleted. function updateElementFields(props, iModel, deleted) { doUpdateFields(props.targetId, props.sourceId, iModel, deleted); } function updateAllFields(annotationElementId, iModel) { doUpdateFields(annotationElementId, undefined, iModel, false); } //# sourceMappingURL=fields.js.map