UNPKG

@itwin/core-backend

Version:
136 lines • 6.34 kB
import { SchemaContext, SchemaGraphUtil, SchemaJsonLocater, SchemaMatchType } from "@itwin/ecschema-metadata"; import { IModelIncrementalSchemaLocater } from "../../IModelIncrementalSchemaLocater"; import { BriefcaseDb, IModelDb, StandaloneDb } from "../../IModelDb"; import { IModelHost } from "../../IModelHost"; import { KnownTestLocations } from "../KnownTestLocations"; import { OpenMode } from "@itwin/core-bentley"; import { IModelJsFs } from "../../IModelJsFs"; import { ProfileOptions } from "@itwin/core-common"; import { SchemaXmlFileLocater } from "@itwin/ecschema-locaters"; import { DOMParser, XMLSerializer } from "@xmldom/xmldom"; import * as path from "path"; export class TestContext { _iModel; _schemaLocater; _assetContext; constructor(iModel) { this._iModel = iModel; this._schemaLocater = this._iModel.schemaContext.locaters.find((locater) => { return locater instanceof IModelIncrementalSchemaLocater; }); // Ideally we should not need a seperate context here to locate and locate the bisschemas from the // parent imodel context, but due to a bug in the incremental schema logic, we have to do this for now. // TODO: remove this when issue #1763 is fixed. this._assetContext = new SchemaContext(); this._assetContext.addLocater(new SchemaJsonLocater((schemaName) => { return iModel.getSchemaProps(schemaName); })); const xmlAssetSchemaLocater = new SchemaXmlFileLocater(); xmlAssetSchemaLocater.addSchemaSearchPath(path.join(KnownTestLocations.assetsDir, "IncrementalSchemaLocater")); this._assetContext.addLocater(xmlAssetSchemaLocater); iModel.schemaContext.addLocater(this._assetContext); } get iModel() { return this._iModel; } get schemaLocater() { return this._schemaLocater; } get schemaContext() { return this._iModel.schemaContext; } static async create(options) { if (!IModelHost.isValid) { await IModelHost.startup(); } const iModel = options?.bimFile ? await this.loadIModelFile(options.bimFile) : await this.createIModel(); const configuration = IModelHost.configuration; if (configuration) { const previousSetting = configuration.incrementalSchemaLoading; configuration.incrementalSchemaLoading = options ? options.incrementalSchemaLoading : "enabled"; iModel.onBeforeClose.addOnce(() => { configuration.incrementalSchemaLoading = previousSetting; }); } return new TestContext(iModel); } static async loadIModelFile(bimFile) { const pathToBriefCase = path.join(KnownTestLocations.assetsDir, bimFile); return BriefcaseDb.open({ fileName: pathToBriefCase, readonly: true, key: "test-iModel", }); } static async createIModel() { const testBimPath = path.join(KnownTestLocations.assetsDir, "IncrementalSchemaLocater", "test-bim.bim"); if (IModelJsFs.existsSync(testBimPath)) { ~IModelJsFs.removeSync(testBimPath); } const localBim = StandaloneDb.createEmpty(testBimPath, { enableTransactions: true, rootSubject: { name: "IncrementalSchemaTestingDb" }, }); localBim.close(); const nativeDb = IModelDb.openDgnDb({ path: testBimPath }, OpenMode.ReadWrite, { profile: ProfileOptions.Upgrade }); nativeDb.saveChanges(); nativeDb.closeFile(); return StandaloneDb.openFile(testBimPath, OpenMode.ReadWrite); } async getSchemaNames() { const result = new Array(); const sqlQuery = "SELECT Name, VersionMajor, VersionWrite, VersionMinor FROM meta.ECSchemaDef ORDER BY Name"; const reader = this._iModel.createQueryReader(sqlQuery); while (await reader.step()) { const name = reader.current[0]; const versionMajor = reader.current[1]; const versionWrite = reader.current[2]; const versionMinor = reader.current[3]; result.push(`${name}.${versionMajor}.${versionWrite}.${versionMinor}`); } return result; } async importAssetSchema(schemaKey) { // If schema is already in the iModel, return it. if (undefined !== this.iModel.querySchemaVersion(schemaKey.name)) return await this.schemaContext.getSchema(schemaKey); // Locate the schema from the assets using the schema contexts asset locaters. const testSchema = await this._assetContext.getSchema(schemaKey, SchemaMatchType.Exact); if (undefined === testSchema) throw new Error(`The schema '${schemaKey.name}' could not be found in the assets folder.`); const schemaXml = await getOrderedSchemaStrings(testSchema); await this._iModel.importSchemaStrings(schemaXml); this._iModel.saveChanges(); if (this.iModel.isBriefcaseDb() && !this.iModel.isReadonly) { await this.iModel.pushChanges({ description: "import test schema" }); } const schema = await this.schemaContext.getSchema(schemaKey); if (undefined === schema) throw new Error(`The schema '${schemaKey.name}' could not be found after import.`); if (schema.loadingController && !schema.loadingController.isComplete) { await schema.loadingController.wait(); } return schema; } async [Symbol.asyncDispose]() { return this._iModel.close(); } } async function getOrderedSchemaStrings(insertSchema) { const schemas = SchemaGraphUtil.buildDependencyOrderedSchemaList(insertSchema); const schemaStrings = await Promise.all(schemas.map(async (schema) => getSchemaString(schema))); return schemaStrings; } async function getSchemaString(schema) { // Serialize schema to the document object const xmlDocument = new DOMParser().parseFromString(`<?xml version="1.0" encoding="UTF-8"?>`, "application/xml"); await schema.toXml(xmlDocument); const serializer = new XMLSerializer(); const xml = serializer.serializeToString(xmlDocument); return xml; } //# sourceMappingURL=TestContext.js.map