UNPKG

@itwin/core-backend

Version:
237 lines • 9.92 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; 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 getFieldProperty(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: 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: { (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; } } } } if (field.propertyPath.jsonAccessors) { if (!ecProp.isPrimitive() || ecProp.isArray() || ecProp.extendedTypeName !== "Json" || typeof curValue.primitive !== "string") { return undefined; } let json = JSON.parse(curValue.primitive); for (const accessor of field.propertyPath.jsonAccessors) { if (typeof accessor === "number") { if (!Array.isArray(json)) { return undefined; } json = json[accessor < 0 ? json.length + accessor : accessor]; } else { if (typeof json !== "object" || json === null) { return undefined; } json = json[accessor]; } } switch (typeof json) { case "string": case "number": case "boolean": curValue = { primitive: json }; break; default: return undefined; } } // The ultimate result must be a primitive value. if (undefined === curValue.primitive) { return undefined; } return { value: curValue.primitive, metadata: { property: ecProp }, }; } function createUpdateContext(hostElementId, iModel, deleted) { return { hostElementId, getProperty: deleted ? () => undefined : (field) => getFieldProperty(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 !== field.propertyHost.elementId) { return false; } let newContent; try { const prop = context.getProperty(field); if (undefined !== prop) { // ###TODO formatting etc. // eslint-disable-next-line @typescript-eslint/no-base-to-string newContent = prop.value.toString(); } } 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 paragraph of textBlock.paragraphs) { for (const run of paragraph.runs) { if (run.type === "field" && updateField(run, context)) { ++numUpdated; } } } return numUpdated; } // Invoked by ElementDrivesTextAnnotation to update fields in target element when source element changes or is deleted. function updateElementFields(props, iModel, deleted) { try { const target = iModel.elements.getElement(props.targetId); if ((0, ElementDrivesTextAnnotation_1.isITextAnnotation)(target)) { const context = createUpdateContext(props.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); } } } catch (err) { core_bentley_1.Logger.logException(BackendLoggerCategory_1.BackendLoggerCategory.IModelDb, err); } } //# sourceMappingURL=fields.js.map