@itwin/core-backend
Version:
iTwin.js backend components
110 lines • 6.27 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 Elements
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ElementDrivesTextAnnotation = void 0;
exports.isITextAnnotation = isITextAnnotation;
const Relationship_1 = require("../Relationship");
const fields_1 = require("../internal/annotations/fields");
const core_bentley_1 = require("@itwin/core-bentley");
const ecschema_metadata_1 = require("@itwin/ecschema-metadata");
// ElementDrivesTextAnnotation was introduced in this version of BisCore - iModels with earlier versions cannot support field dependencies.
const minBisCoreVersion = new ecschema_metadata_1.ECVersion(1, 0, 22);
/** Returns `true` if the specified `element` implements [[ITextAnnotation]].
* @beta
*/
function isITextAnnotation(element) {
return ["getTextBlocks", "updateTextBlocks"].every((x) => x in element && typeof element[x] === "function");
}
/** A relationship in which the source element hosts one or more properties that are displayed by a target [[ITextAnnotation]] element.
* This relationship is used to automatically update the [FieldRun]($common)s contained in the target element when the source element is modified.
* An [[ITextAnnotation]] element should invoke [[updateFieldDependencies]] from its [[Element.onInserted]] and [[Element.onUpdated]] functions to
* establish or update the relationships required for the [FieldRun]($common)s it contains.
* @note This relationship was introduced in version 01.00.22 of the BisCore schema. [FieldRun]($common)s created in iModels that have not been upgraded to
* that version or newer will not automatically update. Use [[isSupportedForIModel]] to check.
* @beta
*/
class ElementDrivesTextAnnotation extends Relationship_1.ElementDrivesElement {
static get className() { return "ElementDrivesTextAnnotation"; }
/** @internal */
static onRootChanged(props, iModel) {
(0, fields_1.updateElementFields)(props, iModel, false);
}
/** @internal */
static onDeletedDependency(props, iModel) {
(0, fields_1.updateElementFields)(props, iModel, true);
}
/** Returns true if `iModel` contains a version of the BisCore schema new enough to support this relationship.
* If not, the schema should be updated before inserting any [FieldRun]($common)s, or those runs will not
* update when the source element changes.
*/
static isSupportedForIModel(iModel) {
const bisCoreVersion = iModel.querySchemaVersionNumbers("BisCore");
return undefined !== bisCoreVersion && bisCoreVersion.compare(minBisCoreVersion) >= 0;
}
/** Examines all of the [FieldRun]($common)s within the specified [[ITextAnnotation]] and ensures that the appropriate
* `ElementDrivesTextAnnotation` relationships exist between the fields' source elements and this target element.
* It also deletes any stale relationships left over from fields that were deleted or whose source elements changed.
*/
static updateFieldDependencies(annotationElementId, iModel) {
if (!ElementDrivesTextAnnotation.isSupportedForIModel(iModel)) {
return;
}
const annotationElement = iModel.elements.tryGetElement(annotationElementId);
if (!annotationElement || !isITextAnnotation(annotationElement)) {
return;
}
// The native layer will allow us to insert relationships to invalid or non-existent source elements...errors will arise later. Prevent it.
function isValidSourceId(id) {
if (!core_bentley_1.Id64.isValidId64(id)) {
return false;
}
// eslint-disable-next-line @typescript-eslint/no-deprecated
return iModel.withPreparedStatement("SELECT CodeValue FROM BisCore.Element WHERE ECInstanceId=?", (stmt) => {
stmt.bindId(1, id);
return core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step();
});
}
const sourceToRelationship = new Map();
const blocks = annotationElement.getTextBlocks();
for (const block of blocks) {
for (const paragraph of block.textBlock.paragraphs) {
for (const run of paragraph.runs) {
if (run.type === "field" && isValidSourceId(run.propertyHost.elementId)) {
sourceToRelationship.set(run.propertyHost.elementId, null);
}
}
}
}
const staleRelationships = new Set();
// eslint-disable-next-line @typescript-eslint/no-deprecated
annotationElement.iModel.withPreparedStatement(`SELECT ECInstanceId, SourceECInstanceId FROM BisCore.ElementDrivesTextAnnotation WHERE TargetECInstanceId=${annotationElement.id}`, (stmt) => {
while (core_bentley_1.DbResult.BE_SQLITE_ROW === stmt.step()) {
const relationshipId = stmt.getValue(0).getId();
const sourceId = stmt.getValue(1).getId();
if (sourceToRelationship.has(sourceId)) {
sourceToRelationship.set(sourceId, relationshipId);
}
else {
staleRelationships.add(relationshipId);
}
}
});
for (const [sourceId, relationshipId] of sourceToRelationship) {
if (relationshipId === null) {
ElementDrivesTextAnnotation.create(annotationElement.iModel, sourceId, annotationElement.id).insert();
}
}
for (const relationshipId of staleRelationships) {
const props = annotationElement.iModel.relationships.getInstanceProps("BisCore.ElementDrivesTextAnnotation", relationshipId);
annotationElement.iModel.relationships.deleteInstance(props);
}
}
}
exports.ElementDrivesTextAnnotation = ElementDrivesTextAnnotation;
//# sourceMappingURL=ElementDrivesTextAnnotation.js.map