@itwin/core-backend
Version:
iTwin.js backend components
172 lines • 8.87 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.IModelElementCloneContext = void 0;
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
* @module iModels
*/
const core_bentley_1 = require("@itwin/core-bentley");
const core_common_1 = require("@itwin/core-common");
const Category_1 = require("./Category");
const NativePlatform_1 = require("./internal/NativePlatform");
const Symbols_1 = require("./internal/Symbols");
/** The context for transforming a *source* Element to a *target* Element and remapping internal identifiers to the target iModel.
* @beta
*/
class IModelElementCloneContext {
/** The source IModelDb. */
sourceDb;
/** The target IModelDb. */
targetDb;
/** The native import context */
_nativeContext;
/** Construct a new IModelElementCloneContext. It must be initialized with `initialize`, consider using [[IModelElementCloneContext.create]] instead
* @param sourceDb The source IModelDb.
* @param targetDb If provided the target IModelDb. If not provided, the source and target are the same IModelDb.
*/
constructor(sourceDb, targetDb) {
this.sourceDb = sourceDb;
this.targetDb = (undefined !== targetDb) ? targetDb : sourceDb;
this._nativeContext = new NativePlatform_1.IModelNative.platform.ImportContext(this.sourceDb[Symbols_1._nativeDb], this.targetDb[Symbols_1._nativeDb]);
}
/** perform necessary initialization to use a clone context, namely caching the reference types in the source's schemas */
async initialize() {
}
/** construct and initialize an IModelElementCloneContext at once, for where you construct in an async context */
static async create(...args) {
const instance = new this(...args);
await instance.initialize();
return instance;
}
/** Returns `true` if this context is for transforming between 2 iModels and `false` if it for transforming within the same iModel. */
get isBetweenIModels() { return this.sourceDb !== this.targetDb; }
/** Dispose any native resources associated with this IModelElementCloneContext. */
[Symbol.dispose]() { this._nativeContext.dispose(); }
/** @deprecated in 5.0 - will not be removed until after 2026-06-13. Use [Symbol.dispose] instead. */
dispose() {
this[Symbol.dispose]();
}
/** Debugging aid that dumps the Id remapping details and other information to the specified output file.
* @internal
*/
dump(outputFileName) { this._nativeContext.dump(outputFileName); }
/** Add a rule that remaps the specified source [CodeSpec]($common) to the specified target [CodeSpec]($common).
* @param sourceCodeSpecName The name of the CodeSpec from the source iModel.
* @param targetCodeSpecName The name of the CodeSpec from the target iModel.
* @throws [[IModelError]] if either CodeSpec could not be found.
*/
remapCodeSpec(sourceCodeSpecName, targetCodeSpecName) {
const sourceCodeSpec = this.sourceDb.codeSpecs.getByName(sourceCodeSpecName);
const targetCodeSpec = this.targetDb.codeSpecs.getByName(targetCodeSpecName);
this._nativeContext.addCodeSpecId(sourceCodeSpec.id, targetCodeSpec.id);
}
/** Add a rule that remaps the specified source class to the specified target class. */
remapElementClass(sourceClassFullName, targetClassFullName) {
this._nativeContext.addClass(sourceClassFullName, targetClassFullName);
}
/** Add a rule that remaps the specified source Element to the specified target Element. */
remapElement(sourceId, targetId) {
this._nativeContext.addElementId(sourceId, targetId);
}
/** Remove a rule that remaps the specified source Element. */
removeElement(sourceId) {
this._nativeContext.removeElementId(sourceId);
}
/** Look up a target CodeSpecId from the source CodeSpecId.
* @returns the target CodeSpecId or [Id64.invalid]($bentley) if a mapping not found.
*/
findTargetCodeSpecId(sourceId) {
if (core_bentley_1.Id64.invalid === sourceId) {
return core_bentley_1.Id64.invalid;
}
return this._nativeContext.findCodeSpecId(sourceId);
}
/** Look up a target ElementId from the source ElementId.
* @returns the target ElementId or [Id64.invalid]($bentley) if a mapping not found.
*/
findTargetElementId(sourceElementId) {
if (core_bentley_1.Id64.invalid === sourceElementId) {
return core_bentley_1.Id64.invalid;
}
return this._nativeContext.findElementId(sourceElementId);
}
/** Filter out geometry entries in the specified SubCategory from GeometryStreams in the target iModel.
* @note It is not possible to filter out a *default* SubCategory. A request to do so will be ignored.
* @see [SubCategory.isDefaultSubCategory]($backend)
*/
filterSubCategory(sourceSubCategoryId) {
const sourceSubCategory = this.sourceDb.elements.tryGetElement(sourceSubCategoryId, Category_1.SubCategory);
if (sourceSubCategory && !sourceSubCategory.isDefaultSubCategory) {
this._nativeContext.filterSubCategoryId(sourceSubCategoryId);
}
}
/** Returns `true` if there are any SubCategories being filtered. */
get hasSubCategoryFilter() {
return this._nativeContext.hasSubCategoryFilter();
}
/** Returns `true` if this SubCategory is being filtered. */
isSubCategoryFiltered(subCategoryId) {
return this._nativeContext.isSubCategoryFiltered(subCategoryId);
}
/** Import the specified font from the source iModel into the target iModel.
* @internal
*/
importFont(sourceFontNumber) {
this.targetDb.clearFontMap(); // so it will be reloaded with new font info
this._nativeContext.importFont(sourceFontNumber);
}
/** Import a single CodeSpec from the source iModel into the target iModel.
* @internal
*/
importCodeSpec(sourceCodeSpecId) {
this._nativeContext.importCodeSpec(sourceCodeSpecId);
}
/** Clone the specified source Element into ElementProps for the target iModel.
* @internal
*/
cloneElement(sourceElement, cloneOptions) {
const targetElementProps = this._nativeContext.cloneElement(sourceElement.id, cloneOptions);
// Ensure that all NavigationProperties in targetElementProps have a defined value so "clearing" changes will be part of the JSON used for update
// eslint-disable-next-line @typescript-eslint/no-deprecated
sourceElement.forEachProperty((propertyName, meta) => {
if ((meta.isNavigation) && (undefined === sourceElement[propertyName])) {
targetElementProps[propertyName] = core_common_1.RelatedElement.none;
}
}, false); // exclude custom because C++ has already handled them
if (this.isBetweenIModels) {
// The native C++ cloneElement strips off federationGuid, want to put it back if transformation is between iModels
targetElementProps.federationGuid = sourceElement.federationGuid;
if (core_common_1.CodeScopeSpec.Type.Repository === this.targetDb.codeSpecs.getById(targetElementProps.code.spec).scopeType) {
targetElementProps.code.scope = core_common_1.IModel.rootSubjectId;
}
}
// unlike other references, code cannot be null. If it is null, use an empty code instead
if (targetElementProps.code.scope === core_bentley_1.Id64.invalid || targetElementProps.code.spec === core_bentley_1.Id64.invalid) {
targetElementProps.code = core_common_1.Code.createEmpty();
}
const jsClass = this.sourceDb.getJsClass(sourceElement.classFullName);
// eslint-disable-next-line @typescript-eslint/dot-notation
jsClass["onCloned"](this, sourceElement.toJSON(), targetElementProps);
return targetElementProps;
}
/**
* serialize state to a sqlite database at a given path
* assumes the database has not already had any context state serialized to it
* @internal
*/
saveStateToDb(db) {
this._nativeContext.saveStateToDb(db[Symbols_1._nativeDb]);
}
/**
* load state from a sqlite database at a given path
* @internal
*/
loadStateFromDb(db) {
this._nativeContext.loadStateFromDb(db[Symbols_1._nativeDb]);
}
}
exports.IModelElementCloneContext = IModelElementCloneContext;
//# sourceMappingURL=IModelElementCloneContext.js.map