UNPKG

@itwin/core-backend

Version:
598 lines • 27.1 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. *--------------------------------------------------------------------------------------------*/ /** @packageDocumentation * @module Models */ Object.defineProperty(exports, "__esModule", { value: true }); exports.WebMercatorModel = exports.DictionaryModel = exports.LinkModel = exports.DocumentListModel = exports.RepositoryModel = exports.DefinitionModel = exports.InformationRecordModel = exports.SheetIndexModel = exports.GroupInformationModel = exports.InformationModel = exports.RoleModel = exports.SheetModel = exports.SectionDrawingModel = exports.DrawingModel = exports.SpatialLocationModel = exports.PhysicalModel = exports.SpatialModel = exports.GraphicalModel3d = exports.GraphicalModel2d = exports.GeometricModel2d = exports.GeometricModel3d = exports.GeometricModel = exports.Model = void 0; // cspell:ignore elid const core_bentley_1 = require("@itwin/core-bentley"); const core_geometry_1 = require("@itwin/core-geometry"); const core_common_1 = require("@itwin/core-common"); const Element_1 = require("./Element"); const Entity_1 = require("./Entity"); const NavigationRelationship_1 = require("./NavigationRelationship"); const Symbols_1 = require("./internal/Symbols"); /** A Model is a container for persisting a collection of related elements within an iModel. * See [[IModelDb.Models]] for how to query and manage the Models in an IModelDb. * See [Creating models]($docs/learning/backend/CreateModels.md) * @public @preview */ class Model extends Entity_1.Entity { static get className() { return "Model"; } /** @internal */ static get protectedOperations() { return ["onInsert", "onUpdate", "onDelete"]; } modeledElement; name; parentModel; jsonProperties; isPrivate; isTemplate; constructor(props, iModel) { super(props, iModel); this.modeledElement = new core_common_1.RelatedElement(props.modeledElement); this.name = props.name ? props.name : ""; // NB this isn't really a property of Model (it's the code.value of the modeled element), but it comes in ModelProps because it's often needed this.parentModel = props.parentModel; this.isPrivate = core_bentley_1.JsonUtils.asBool(props.isPrivate); this.isTemplate = core_bentley_1.JsonUtils.asBool(props.isTemplate); this.jsonProperties = { ...props.jsonProperties }; // make sure we have our own copy } /** * Model custom HandledProps includes 'isPrivate', 'isTemplate', and 'lastMod'. * @inheritdoc * @beta */ static _customHandledProps = [ { propertyName: "isPrivate", source: "Class" }, { propertyName: "isTemplate", source: "Class" }, { propertyName: "lastMod", source: "Class" }, ]; /** * Model deserializes 'isPrivate', and 'isTemplate', and sets the proper parentModel. * @inheritdoc * @beta */ static deserialize(props) { const instance = props.row; const modelProps = super.deserialize(props); const modeledElementProps = props.iModel.elements.tryGetElementProps(instance.modeledElement.id); if (modeledElementProps) { // ModeledElement may be undefined in the case of root Element modelProps.name = core_bentley_1.JsonUtils.asString(modeledElementProps.code.value); if (instance.parentModel !== undefined) modelProps.parentModel = instance.parentModel.id; else modelProps.parentModel = modeledElementProps.model; } if (instance.isPrivate === true) modelProps.isPrivate = true; if (instance.isTemplate === true) modelProps.isTemplate = true; return modelProps; } /** * Model serializes 'isPrivate', and 'isTemplate'. * @inheritdoc * @beta */ static serialize(props, _iModel) { const inst = super.serialize(props, _iModel); inst.isPrivate = props.isPrivate ?? false; inst.isTemplate = props.isTemplate ?? false; return inst; } toJSON() { const val = super.toJSON(); val.name = this.name; // for cloning return val; } /** Called before a new Model is inserted. * @note throw an exception to disallow the insert * @note If you override this method, you must call super. * @note `this` is the class of the Model to be inserted * @beta */ static onInsert(arg) { const { props, iModel } = arg; iModel.channels[Symbols_1._verifyChannel](props.modeledElement.id); if (props.parentModel) // inserting requires shared lock on parent, if present iModel.locks.checkSharedLock(props.parentModel, "parent model", "insert"); } /** Called after a new Model is inserted. * @note If you override this method, you must call super. * @note `this` is the class of the Model that was inserted * @beta */ static onInserted(_arg) { // we don't need to tell LockControl about models being created - their ModeledElement does that } /** Called before a Model is updated. * @note throw an exception to disallow the update * @note If you override this method, you must call super. * @note `this` is the class of the Model to be updated * @beta */ static onUpdate(arg) { const id = arg.props.id; // eslint-disable-line @typescript-eslint/no-non-null-assertion arg.iModel.channels[Symbols_1._verifyChannel](id); arg.iModel.locks.checkExclusiveLock(id, "model", "update"); } /** Called after a Model is updated. * @note If you override this method, you must call super. * @note `this` is the class of the Model that was updated. * @beta */ static onUpdated(arg) { arg.iModel.models[Symbols_1._cache].delete(arg.id); } /** Called before a Model is deleted. * @note throw an exception to disallow the delete * @note If you override this method, you must call super. * @note `this` is the class of the Model to be deleted * @beta */ static onDelete(arg) { arg.iModel.channels[Symbols_1._verifyChannel](arg.id); arg.iModel.locks.checkExclusiveLock(arg.id, "model", "delete"); } /** Called after a Model was deleted. * @note If you override this method, you must call super. * @note `this` is the class of the Model that was deleted * @beta */ static onDeleted(arg) { arg.iModel.models[Symbols_1._cache].delete(arg.id); arg.iModel.elements[Symbols_1._cache].deleteWithModel(arg.id); } /** Called before a prospective Element is to be inserted into an instance of a Model of this class. * @note throw an exception to disallow the insert * @note If you override this method, you must call super. * @note `this` is the class of the Model to hold the element * @beta */ static onInsertElement(_arg) { } /** Called after an Element has been inserted into an instance of a Model of this class. * @note If you override this method, you must call super. * @note `this` is the class of the Model holding the element * @beta */ static onInsertedElement(arg) { arg.iModel.models[Symbols_1._cache].delete(arg.id); } /** Called when an Element in an instance of a Model of this class is about to be updated. * @note throw an exception to disallow the update * @note If you override this method, you must call super. * @note `this` is the class of the Model holding the element * @beta */ static onUpdateElement(_arg) { } /** Called after an Element in an instance of a Model of this class has been updated. * @note If you override this method, you must call super. * @note `this` is the class of the Model holding the element * @beta */ static onUpdatedElement(arg) { arg.iModel.models[Symbols_1._cache].delete(arg.id); } /** Called when an Element in an instance of a Model of this class is about to be deleted. * @note throw an exception to disallow the delete * @note If you override this method, you must call super. * @note `this` is the class of the Model holding the element * @beta */ static onDeleteElement(_arg) { } /** Called after an Element in an instance of a Model of this class has been deleted. * @note If you override this method, you must call super. * @note `this` is the class of the Model that held the element * @beta */ static onDeletedElement(arg) { arg.iModel.models[Symbols_1._cache].delete(arg.id); } getAllUserProperties() { if (!this.jsonProperties.UserProps) this.jsonProperties.UserProps = new Object(); return this.jsonProperties.UserProps; } /** Get a set of JSON user properties by namespace */ getUserProperties(namespace) { return this.getAllUserProperties()[namespace]; } /** Change a set of user JSON properties of this Element by namespace. */ setUserProperties(nameSpace, value) { this.getAllUserProperties()[nameSpace] = value; } /** Remove a set of JSON user properties, specified by namespace, from this Element */ removeUserProperties(nameSpace) { delete this.getAllUserProperties()[nameSpace]; } getJsonProperty(name) { return this.jsonProperties[name]; } setJsonProperty(name, value) { this.jsonProperties[name] = value; } /** Insert this Model in the iModel */ insert() { return this.id = this.iModel.models.insertModel(this.toJSON()); } /** Update this Model in the iModel. */ update() { this.iModel.models.updateModel(this.toJSON()); } /** Delete this Model from the iModel. */ delete() { this.iModel.models.deleteModel(this.id); } collectReferenceIds(referenceIds) { super.collectReferenceIds(referenceIds); if (this.parentModel) referenceIds.addModel(this.parentModel); referenceIds.addElement(this.modeledElement.id); } } exports.Model = Model; /** A container for persisting geometric elements. * @public @preview */ class GeometricModel extends Model { geometryGuid; static get className() { return "GeometricModel"; } constructor(props, iModel) { super(props, iModel); this.geometryGuid = props.geometryGuid; } /** Query for the union of the extents of the elements contained by this model. * @note This function blocks the JavaScript event loop. Consider using [[queryRange]] instead. */ queryExtents() { const extents = this.iModel[Symbols_1._nativeDb].queryModelExtents({ id: this.id }).modelExtents; return core_geometry_1.Range3d.fromJSON(extents); } /** Query for the union of the extents of all elements contained within this model. */ async queryRange() { return this.iModel.models.queryRange(this.id); } } exports.GeometricModel = GeometricModel; /** A container for persisting 3d geometric elements. * @public @preview */ class GeometricModel3d extends GeometricModel { /** If true, then the elements in this GeometricModel3d are expected to be in an XY plane. * @note The associated ECProperty was added to the BisCore schema in version 1.0.8 */ isPlanProjection; /** If true, then the elements in this GeometricModel3d are not in real-world coordinates and will not be in the spatial index. * @note The associated ECProperty was added to the BisCore schema in version 1.0.8 */ isNotSpatiallyLocated; /** If true, then the elements in this GeometricModel3d are in real-world coordinates and will be in the spatial index. */ get isSpatiallyLocated() { return !this.isNotSpatiallyLocated; } static get className() { return "GeometricModel3d"; } constructor(props, iModel) { super(props, iModel); this.isNotSpatiallyLocated = core_bentley_1.JsonUtils.asBool(props.isNotSpatiallyLocated); this.isPlanProjection = core_bentley_1.JsonUtils.asBool(props.isPlanProjection); } /** * GeometricModel3d custom HandledProps includes 'isPlanProjection', and 'isNotSpatiallyLocated'. * @inheritdoc * @beta */ static _customHandledProps = [ { propertyName: "isPlanProjection", source: "Class" }, { propertyName: "isNotSpatiallyLocated", source: "Class" }, ]; /** * GeometricModel3d deserializes 'isPlanProjection', and 'isNotSpatiallyLocated'. * @inheritdoc * @beta */ static deserialize(props) { const modelProps = super.deserialize(props); const instance = props.row; if (instance.isNotSpatiallyLocated === true || instance.isTemplate === true) modelProps.isNotSpatiallyLocated = true; if (instance.isPlanProjection === true) modelProps.isPlanProjection = true; return modelProps; } /** * GeometricModel3d serializes 'isPlanProjection', and 'isNotSpatiallyLocated'. * @inheritdoc * @beta */ static serialize(props, _iModel) { const inst = super.serialize(props, _iModel); inst.isNotSpatiallyLocated = props.isNotSpatiallyLocated ?? false; inst.isPlanProjection = props.isPlanProjection ?? false; return inst; } toJSON() { const val = super.toJSON(); if (this.isNotSpatiallyLocated) val.isNotSpatiallyLocated = true; if (this.isPlanProjection) val.isPlanProjection = true; return val; } } exports.GeometricModel3d = GeometricModel3d; /** A container for persisting 2d geometric elements. * @public @preview */ class GeometricModel2d extends GeometricModel { /** The actual coordinates of (0,0) in modeling coordinates. An offset applied to all modeling coordinates. */ globalOrigin; static get className() { return "GeometricModel2d"; } constructor(props, iModel) { super(props, iModel); this.globalOrigin = props.globalOrigin ? core_geometry_1.Point2d.fromJSON(props.globalOrigin) : undefined; } toJSON() { const val = super.toJSON(); if (undefined !== this.globalOrigin) val.globalOrigin = core_geometry_1.Point2d.fromJSON(this.globalOrigin); return val; } } exports.GeometricModel2d = GeometricModel2d; /** A container for persisting 2d graphical elements. * @public @preview */ class GraphicalModel2d extends GeometricModel2d { static get className() { return "GraphicalModel2d"; } } exports.GraphicalModel2d = GraphicalModel2d; /** A container for persisting GraphicalElement3d instances. * @note The associated ECClass was added to the BisCore schema in version 1.0.8 * @see [[GraphicalPartition3d]] * @public @preview */ class GraphicalModel3d extends GeometricModel3d { static get className() { return "GraphicalModel3d"; } } exports.GraphicalModel3d = GraphicalModel3d; /** A container for persisting 3d geometric elements that are spatially located. * @public @preview */ class SpatialModel extends GeometricModel3d { static get className() { return "SpatialModel"; } } exports.SpatialModel = SpatialModel; /** A container for persisting physical elements that model physical space. * @see [[PhysicalPartition]] * @public @preview */ class PhysicalModel extends SpatialModel { static get className() { return "PhysicalModel"; } /** Insert a PhysicalPartition and a PhysicalModel that sub-models it. * @param iModelDb Insert into this iModel * @param parentSubjectId The PhysicalPartition will be inserted as a child of this Subject element. * @param name The name of the PhysicalPartition that the new PhysicalModel will sub-model. * @param isPlanProjection Optional value (default is false) that indicates if the contents of this model are expected to be in an XY plane. * @returns The Id of the newly inserted PhysicalPartition and PhysicalModel (same value). * @throws [[IModelError]] if there is an insert problem. */ static insert(iModelDb, parentSubjectId, name, isPlanProjection) { const partitionProps = { classFullName: Element_1.PhysicalPartition.classFullName, model: core_common_1.IModel.repositoryModelId, parent: new NavigationRelationship_1.SubjectOwnsPartitionElements(parentSubjectId), code: Element_1.PhysicalPartition.createCode(iModelDb, parentSubjectId, name), }; const partitionId = iModelDb.elements.insertElement(partitionProps); const modelProps = { classFullName: this.classFullName, modeledElement: { id: partitionId }, isPlanProjection, }; return iModelDb.models.insertModel(modelProps); } } exports.PhysicalModel = PhysicalModel; /** A container for persisting spatial location elements. * @see [[SpatialLocationPartition]] * @public @preview */ class SpatialLocationModel extends SpatialModel { static get className() { return "SpatialLocationModel"; } /** Insert a SpatialLocationPartition and a SpatialLocationModel that sub-models it. * @param iModelDb Insert into this iModel * @param parentSubjectId The SpatialLocationPartition will be inserted as a child of this Subject element. * @param name The name of the SpatialLocationPartition that the new SpatialLocationModel will sub-model. * @param isPlanProjection Optional value (default is false) that indicates if the contents of this model are expected to be in an XY plane. * @returns The Id of the newly inserted SpatialLocationPartition and SpatialLocationModel (same value). * @throws [[IModelError]] if there is an insert problem. */ static insert(iModelDb, parentSubjectId, name, isPlanProjection) { const partitionProps = { classFullName: Element_1.SpatialLocationPartition.classFullName, model: core_common_1.IModel.repositoryModelId, parent: new NavigationRelationship_1.SubjectOwnsPartitionElements(parentSubjectId), code: Element_1.SpatialLocationPartition.createCode(iModelDb, parentSubjectId, name), }; const partitionId = iModelDb.elements.insertElement(partitionProps); const modelProps = { classFullName: this.classFullName, modeledElement: { id: partitionId }, isPlanProjection, }; return iModelDb.models.insertModel(modelProps); } } exports.SpatialLocationModel = SpatialLocationModel; /** A 2d model that holds [[DrawingGraphic]]s. DrawingModels may be dimensional or non-dimensional. * @public @preview */ class DrawingModel extends GraphicalModel2d { static get className() { return "DrawingModel"; } } exports.DrawingModel = DrawingModel; /** A container for persisting section [[DrawingGraphic]]s. * @public @preview */ class SectionDrawingModel extends DrawingModel { static get className() { return "SectionDrawingModel"; } } exports.SectionDrawingModel = SectionDrawingModel; /** A container for persisting [[ViewAttachment]]s and [[DrawingGraphic]]s. * A SheetModel is a digital representation of a *sheet of paper*. SheetModels are 2d models in bounded paper coordinates. * SheetModels may contain annotation Elements as well as references to 2d or 3d Views. * @public @preview */ class SheetModel extends GraphicalModel2d { static get className() { return "SheetModel"; } } exports.SheetModel = SheetModel; /** A container for persisting role elements. * @public @preview */ class RoleModel extends Model { static get className() { return "RoleModel"; } } exports.RoleModel = RoleModel; /** A container for persisting information elements. * @public @preview */ class InformationModel extends Model { static get className() { return "InformationModel"; } } exports.InformationModel = InformationModel; /** A container for persisting group information elements. * @see [[GroupInformationPartition]] * @public @preview */ class GroupInformationModel extends InformationModel { static get className() { return "GroupInformationModel"; } } exports.GroupInformationModel = GroupInformationModel; /** A sub-model of a [[SheetIndexPartition]] serving as a container for persisting [[SheetIndexEntry]] and [[SheetIndex]] elements. * @beta */ class SheetIndexModel extends InformationModel { static get className() { return "SheetIndexModel"; } /** Insert a SheetIndex and a SheetIndexModel that sub-models it. * @param iModelDb Insert into this iModel * @param parentSubjectId The SheetIndex will be inserted as a child of this Subject element. * @param name The name of the SheetIndex that the new SheetIndexModel will sub-model. * @returns The Id of the newly inserted SheetIndexModel. * @throws [[IModelError]] if there is an insert problem. */ static insert(iModelDb, parentSubjectId, name) { const sheetIndex = { classFullName: Element_1.SheetIndexPartition.classFullName, model: core_common_1.IModel.repositoryModelId, parent: new NavigationRelationship_1.SubjectOwnsPartitionElements(parentSubjectId), code: Element_1.SheetIndexPartition.createCode(iModelDb, parentSubjectId, name), }; const partitionId = iModelDb.elements.insertElement(sheetIndex); return iModelDb.models.insertModel({ classFullName: this.classFullName, modeledElement: { id: partitionId }, }); } } exports.SheetIndexModel = SheetIndexModel; /** A container for persisting Information Record Elements * @see [[InformationRecordPartition]] * @public @preview */ class InformationRecordModel extends InformationModel { static get className() { return "InformationRecordModel"; } /** Insert a InformationRecordPartition and a InformationRecordModel that sub-models it. * @param iModelDb Insert into this iModel * @param parentSubjectId The InformationRecordPartition will be inserted as a child of this Subject element. * @param name The name of the InformationRecordPartition that the new InformationRecordModel will sub-model. * @returns The Id of the newly inserted InformationRecordModel. * @throws [[IModelError]] if there is an insert problem. */ static insert(iModelDb, parentSubjectId, name) { const partitionProps = { classFullName: Element_1.InformationRecordPartition.classFullName, model: core_common_1.IModel.repositoryModelId, parent: new NavigationRelationship_1.SubjectOwnsPartitionElements(parentSubjectId), code: Element_1.InformationRecordPartition.createCode(iModelDb, parentSubjectId, name), }; const partitionId = iModelDb.elements.insertElement(partitionProps); return iModelDb.models.insertModel({ classFullName: this.classFullName, modeledElement: { id: partitionId }, }); } } exports.InformationRecordModel = InformationRecordModel; /** A container for persisting definition elements. * @see [[DefinitionPartition]] * @public @preview */ class DefinitionModel extends InformationModel { static get className() { return "DefinitionModel"; } /** Insert a DefinitionPartition and a DefinitionModel that sub-models it. * @param iModelDb Insert into this iModel * @param parentSubjectId The DefinitionPartition will be inserted as a child of this Subject element. * @param name The name of the DefinitionPartition that the new DefinitionModel will sub-model. * @returns The Id of the newly inserted DefinitionModel. * @throws [[IModelError]] if there is an insert problem. */ static insert(iModelDb, parentSubjectId, name) { const partitionProps = { classFullName: Element_1.DefinitionPartition.classFullName, model: core_common_1.IModel.repositoryModelId, parent: new NavigationRelationship_1.SubjectOwnsPartitionElements(parentSubjectId), code: Element_1.DefinitionPartition.createCode(iModelDb, parentSubjectId, name), }; const partitionId = iModelDb.elements.insertElement(partitionProps); return iModelDb.models.insertModel({ classFullName: this.classFullName, modeledElement: { id: partitionId }, }); } } exports.DefinitionModel = DefinitionModel; /** The singleton container of repository-related information elements. * @public @preview */ class RepositoryModel extends DefinitionModel { static get className() { return "RepositoryModel"; } } exports.RepositoryModel = RepositoryModel; /** Contains a list of document elements. * @see [[DocumentPartition]] * @public @preview */ class DocumentListModel extends InformationModel { static get className() { return "DocumentListModel"; } /** Insert a DocumentPartition and a DocumentListModel that sub-models it. * @param iModelDb Insert into this iModel * @param parentSubjectId The DocumentPartition will be inserted as a child of this Subject element. * @param name The name of the DocumentPartition that the new DocumentListModel will sub-model. * @returns The Id of the newly inserted DocumentPartition and DocumentListModel (same value) * @throws [[IModelError]] if there is an insert problem. */ static insert(iModelDb, parentSubjectId, name) { const partitionProps = { classFullName: Element_1.DocumentPartition.classFullName, model: core_common_1.IModel.repositoryModelId, parent: new NavigationRelationship_1.SubjectOwnsPartitionElements(parentSubjectId), code: Element_1.DocumentPartition.createCode(iModelDb, parentSubjectId, name), }; const partitionId = iModelDb.elements.insertElement(partitionProps); return iModelDb.models.insertModel({ classFullName: this.classFullName, modeledElement: { id: partitionId }, }); } } exports.DocumentListModel = DocumentListModel; /** A container for persisting link elements. * @see [[LinkPartition]] * @public @preview */ class LinkModel extends InformationModel { static get className() { return "LinkModel"; } } exports.LinkModel = LinkModel; /** The singleton container for repository-specific definition elements. * @public @preview */ class DictionaryModel extends DefinitionModel { static get className() { return "DictionaryModel"; } } exports.DictionaryModel = DictionaryModel; /** Obtains and displays multi-resolution tiled raster organized according to the WebMercator tiling system. * @public @preview */ class WebMercatorModel extends SpatialModel { static get className() { return "WebMercatorModel"; } } exports.WebMercatorModel = WebMercatorModel; //# sourceMappingURL=Model.js.map