UNPKG

@itwin/core-backend

Version:
156 lines • 7.71 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 Codes */ Object.defineProperty(exports, "__esModule", { value: true }); exports.CodeSpecs = void 0; const core_bentley_1 = require("@itwin/core-bentley"); const core_common_1 = require("@itwin/core-common"); /** Manages [CodeSpecs]($docs/BIS/guide/fundamentals/element-fundamentals.md#codespec) within an [[IModelDb]] * @public @preview */ class CodeSpecs { static tableName = "bis_CodeSpec"; _imodel; _loadedCodeSpecs = []; constructor(imodel) { this._imodel = imodel; if (imodel.isBriefcaseDb()) { imodel.onChangesetApplied.addListener(() => this._loadedCodeSpecs.length = 0); } } findByName(name) { return this._imodel.withSqliteStatement(`SELECT Id FROM ${CodeSpecs.tableName} WHERE Name=?`, (stmt) => { stmt.bindString(1, name); return stmt.nextRow() ? stmt.getValueId(0) : undefined; }); } /** Look up the Id of the CodeSpec with the specified name. */ queryId(name) { const id = this.findByName(name); if (!id) throw new core_common_1.IModelError(core_bentley_1.IModelStatus.NotFound, "CodeSpec not found"); return id; } /** Look up a CodeSpec by Id. The CodeSpec will be loaded from the database if necessary. * @param codeSpecId The Id of the CodeSpec to load * @returns The CodeSpec with the specified Id * @throws [[IModelError]] if the Id is invalid or if no CodeSpec with that Id could be found. */ getById(codeSpecId) { // good chance it is already loaded - check there before running a query const found = this._loadedCodeSpecs.find((codeSpec) => codeSpec.id === codeSpecId); if (found !== undefined) return found; // must load this codespec const loadedCodeSpec = this.load(codeSpecId); this._loadedCodeSpecs.push(loadedCodeSpec); return loadedCodeSpec; } /** Returns true if the IModelDb has a CodeSpec of the specified Id. */ hasId(codeSpecId) { try { return undefined !== this.getById(codeSpecId); } catch { return false; } } /** Look up a CodeSpec by name. The CodeSpec will be loaded from the database if necessary. * @param name The name of the CodeSpec to load * @returns The CodeSpec with the specified name * @throws [[IModelError]] if no CodeSpec with the specified name could be found. */ getByName(name) { // good chance it is already loaded - check there before running a query const found = this._loadedCodeSpecs.find((codeSpec) => codeSpec.name === name); if (found !== undefined) return found; const codeSpecId = this.queryId(name); if (codeSpecId === undefined) throw new core_common_1.IModelError(core_bentley_1.IModelStatus.NotFound, "CodeSpec not found"); return this.getById(codeSpecId); } /** Returns true if the IModelDb has a CodeSpec of the specified name. */ hasName(name) { try { return undefined !== this.getByName(name); } catch { return false; } } insertCodeSpec(specName, properties) { const iModel = this._imodel; const spec = { name: specName.trim(), props: JSON.stringify(properties) }; if (this.findByName(spec.name)) throw new core_common_1.IModelError(core_bentley_1.IModelStatus.DuplicateName, "CodeSpec already exists"); const internalCodes = iModel.codeService?.internalCodes; if (internalCodes) { // Since there is no lock on the codespec table, to add a codespec to an iModel it must first be reserved in the // internal code index via `internalCodes.reserveBisCodeSpecs` prior to calling this function. // This ensures that the Ids will be unique, and the property values consistent, even if more than one user // adds them without pushing their changes. The call to `verifyBisCodeSpec` will throw otherwise. internalCodes.reader.verifyBisCodeSpec(spec); } else { // If this iModel doesn't have an internal code index, we have no way of coordinating the Ids for CodeSpecs across multiple users. // Just look in this briefcase to find the currently highest used Id and hope for the best. spec.id = iModel.withSqliteStatement(`SELECT MAX(Id) FROM ${CodeSpecs.tableName}`, (stmt) => stmt.nextRow() ? stmt.getValueInteger(0) + 1 : 1); } const id = spec.id; // eslint-disable-line @typescript-eslint/no-non-null-assertion iModel.withSqliteStatement(`INSERT INTO ${CodeSpecs.tableName}(Id,Name,JsonProperties) VALUES(?,?,?)`, (stmt) => { stmt.bindInteger(1, id); stmt.bindString(2, spec.name); stmt.bindString(3, spec.props); const rc = stmt.step(); if (rc !== core_bentley_1.DbResult.BE_SQLITE_DONE) throw new core_bentley_1.BentleyError(rc, "Error inserting codeSpec"); }); return core_bentley_1.Id64.fromLocalAndBriefcaseIds(id, 0); } insert(codeSpecOrName, props) { if (codeSpecOrName instanceof core_common_1.CodeSpec) { const id = this.insertCodeSpec(codeSpecOrName.name, codeSpecOrName.properties); codeSpecOrName.id = id; return id; } if (props === undefined) throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, "Invalid argument"); if (typeof props === "object") return this.insertCodeSpec(codeSpecOrName, props); const spec = core_common_1.CodeSpec.create(this._imodel, codeSpecOrName, props); return this.insertCodeSpec(spec.name, spec.properties); } /** Update the Json properties of an existing CodeSpec. * @param codeSpec The codeSpec holding Json properties values to update * @throws if unable to update the codeSpec. */ updateProperties(codeSpec) { this._imodel.withSqliteStatement(`UPDATE ${CodeSpecs.tableName} SET JsonProperties=? WHERE Id=?`, (stmt) => { stmt.bindString(1, JSON.stringify(codeSpec.properties)); stmt.bindId(2, codeSpec.id); if (core_bentley_1.DbResult.BE_SQLITE_DONE !== stmt.step()) throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadArg, "error updating CodeSpec properties"); }); } /** Load a CodeSpec from the iModel * @param id The persistent Id of the CodeSpec to load */ load(id) { if (core_bentley_1.Id64.isInvalid(id)) throw new core_common_1.IModelError(core_bentley_1.IModelStatus.InvalidId, "Invalid codeSpecId"); return this._imodel.withSqliteStatement(`SELECT Name,JsonProperties FROM ${CodeSpecs.tableName} WHERE Id=?`, (stmt) => { stmt.bindId(1, id); if (!stmt.nextRow()) throw new core_common_1.IModelError(core_bentley_1.IModelStatus.InvalidId, "CodeSpec not found"); return core_common_1.CodeSpec.createFromJson(this._imodel, id, stmt.getValueString(0), JSON.parse(stmt.getValueString(1))); }); } } exports.CodeSpecs = CodeSpecs; //# sourceMappingURL=CodeSpecs.js.map