@itwin/imodel-transformer 2.0.0-dev.34 → 2.0.0-dev.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +10 -0
  2. package/lib/cjs/ElementAspectCleanup.d.ts +16 -0
  3. package/lib/cjs/ElementAspectCleanup.d.ts.map +1 -0
  4. package/lib/cjs/ElementAspectCleanup.js +83 -0
  5. package/lib/cjs/ElementAspectCleanup.js.map +1 -0
  6. package/lib/cjs/ElementAspectExportCoordinator.d.ts +44 -0
  7. package/lib/cjs/ElementAspectExportCoordinator.d.ts.map +1 -0
  8. package/lib/cjs/ElementAspectExportCoordinator.js +148 -0
  9. package/lib/cjs/ElementAspectExportCoordinator.js.map +1 -0
  10. package/lib/cjs/ElementAspectExportProcessor.d.ts +55 -0
  11. package/lib/cjs/ElementAspectExportProcessor.d.ts.map +1 -0
  12. package/lib/cjs/ElementAspectExportProcessor.js +186 -0
  13. package/lib/cjs/ElementAspectExportProcessor.js.map +1 -0
  14. package/lib/cjs/IModelCloneContext.d.ts +3 -2
  15. package/lib/cjs/IModelCloneContext.d.ts.map +1 -1
  16. package/lib/cjs/IModelCloneContext.js +3 -2
  17. package/lib/cjs/IModelCloneContext.js.map +1 -1
  18. package/lib/cjs/IModelExporter.d.ts +48 -10
  19. package/lib/cjs/IModelExporter.d.ts.map +1 -1
  20. package/lib/cjs/IModelExporter.js +368 -41
  21. package/lib/cjs/IModelExporter.js.map +1 -1
  22. package/lib/cjs/IModelImporter.d.ts +6 -0
  23. package/lib/cjs/IModelImporter.d.ts.map +1 -1
  24. package/lib/cjs/IModelImporter.js +9 -0
  25. package/lib/cjs/IModelImporter.js.map +1 -1
  26. package/lib/cjs/IModelTransformContext.d.ts +54 -0
  27. package/lib/cjs/IModelTransformContext.d.ts.map +1 -0
  28. package/lib/cjs/IModelTransformContext.js +3 -0
  29. package/lib/cjs/IModelTransformContext.js.map +1 -0
  30. package/lib/cjs/IModelTransformer.d.ts +7 -3
  31. package/lib/cjs/IModelTransformer.d.ts.map +1 -1
  32. package/lib/cjs/IModelTransformer.js +57 -30
  33. package/lib/cjs/IModelTransformer.js.map +1 -1
  34. package/lib/cjs/IModelTransformerError.d.ts +2 -0
  35. package/lib/cjs/IModelTransformerError.d.ts.map +1 -1
  36. package/lib/cjs/IModelTransformerError.js +2 -0
  37. package/lib/cjs/IModelTransformerError.js.map +1 -1
  38. package/lib/cjs/ProvenanceManager.d.ts +8 -3
  39. package/lib/cjs/ProvenanceManager.d.ts.map +1 -1
  40. package/lib/cjs/ProvenanceManager.js +23 -23
  41. package/lib/cjs/ProvenanceManager.js.map +1 -1
  42. package/lib/cjs/SyncTypeResolver.d.ts +3 -3
  43. package/lib/cjs/SyncTypeResolver.d.ts.map +1 -1
  44. package/lib/cjs/SyncTypeResolver.js +6 -4
  45. package/lib/cjs/SyncTypeResolver.js.map +1 -1
  46. package/lib/cjs/TransformerLoggerCategory.d.ts +1 -1
  47. package/lib/cjs/TransformerLoggerCategory.js +1 -1
  48. package/lib/cjs/TransformerLoggerCategory.js.map +1 -1
  49. package/lib/cjs/imodel-transformer.d.ts +10 -1
  50. package/lib/cjs/imodel-transformer.d.ts.map +1 -1
  51. package/lib/cjs/imodel-transformer.js +10 -1
  52. package/lib/cjs/imodel-transformer.js.map +1 -1
  53. package/package.json +1 -1
  54. package/lib/cjs/DetachedExportElementAspectsStrategy.d.ts +0 -16
  55. package/lib/cjs/DetachedExportElementAspectsStrategy.d.ts.map +0 -1
  56. package/lib/cjs/DetachedExportElementAspectsStrategy.js +0 -108
  57. package/lib/cjs/DetachedExportElementAspectsStrategy.js.map +0 -1
  58. package/lib/cjs/ExportElementAspectsStrategy.d.ts +0 -35
  59. package/lib/cjs/ExportElementAspectsStrategy.d.ts.map +0 -1
  60. package/lib/cjs/ExportElementAspectsStrategy.js +0 -52
  61. package/lib/cjs/ExportElementAspectsStrategy.js.map +0 -1
  62. package/lib/cjs/ExportElementAspectsWithElementsStrategy.d.ts +0 -12
  63. package/lib/cjs/ExportElementAspectsWithElementsStrategy.d.ts.map +0 -1
  64. package/lib/cjs/ExportElementAspectsWithElementsStrategy.js +0 -48
  65. package/lib/cjs/ExportElementAspectsWithElementsStrategy.js.map +0 -1
@@ -80,8 +80,12 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
80
80
  sourceDb;
81
81
  /** The read/write target iModel. */
82
82
  targetDb;
83
- /** The IModelTransformContext for this IModelTransformer. */
84
- context;
83
+ /** The supported transformation context for this transformer. */
84
+ get context() {
85
+ return this._cloneContext;
86
+ }
87
+ /** The clone context used by the transformer implementation. */
88
+ _cloneContext;
85
89
  /** The transform to be applied to the placement of spatial elements
86
90
  * This transform should be applied when:
87
91
  * - source and target db have different ECEF locations
@@ -196,8 +200,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
196
200
  this.targetDb = this.importer.targetDb;
197
201
  this._targetEditTxn = this.importer.editTxn;
198
202
  this._sourceEditTxn = options?.sourceEditTxn;
203
+ this.exporter.elementAspectExportCoordinator.setPreparation(async (excludedClasses, elementIds) => this.prepareElementAspects(excludedClasses, elementIds));
199
204
  // create the IModelCloneContext, it must be initialized later
200
- this.context = new IModelCloneContext_1.IModelCloneContext(this.sourceDb, this.targetDb);
205
+ this._cloneContext = new IModelCloneContext_1.IModelCloneContext(this.sourceDb, this.targetDb);
201
206
  // this internal is guaranteed stable for just transformer usage
202
207
  /* eslint-disable @itwin/no-internal */
203
208
  if (("codeValueBehavior" in this.sourceDb)) {
@@ -205,8 +210,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
205
210
  this.targetDb.codeValueBehavior = "exact";
206
211
  }
207
212
  /* eslint-enable @itwin/no-internal */
208
- this._syncTypeResolver = new SyncTypeResolver_1.SyncTypeResolver(this.context, this._options.targetScopeElementId, !!this._isProvenanceInitTransform, !!this._options.argsForProcessChanges);
209
- this._provenanceManager = new ProvenanceManager_1.ProvenanceManager(this._options.targetScopeElementId, this._options, this._syncTypeResolver, this._targetEditTxn, this._sourceEditTxn);
213
+ this._syncTypeResolver = new SyncTypeResolver_1.SyncTypeResolver(this.sourceDb, this.targetDb, this._options.targetScopeElementId, !!this._isProvenanceInitTransform, !!this._options.argsForProcessChanges);
214
+ this._provenanceManager = new ProvenanceManager_1.ProvenanceManager(this._options.targetScopeElementId, this._options, this._cloneContext, this._syncTypeResolver, this._targetEditTxn, this._sourceEditTxn);
210
215
  if (this._options.tryAlignGeolocation) {
211
216
  if (this.sourceDb.geographicCoordinateSystem ||
212
217
  this.targetDb.geographicCoordinateSystem) {
@@ -250,7 +255,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
250
255
  /** Dispose any native resources associated with this IModelTransformer. */
251
256
  dispose() {
252
257
  core_bentley_1.Logger.logTrace(loggerCategory, "dispose()");
253
- this.context[Symbol.dispose]();
258
+ this._cloneContext[Symbol.dispose]();
254
259
  }
255
260
  /** Log current settings that affect IModelTransformer's behavior. */
256
261
  logSettings() {
@@ -347,7 +352,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
347
352
  */
348
353
  async onTransformElement(sourceElement) {
349
354
  core_bentley_1.Logger.logTrace(loggerCategory, `onTransformElement(${sourceElement.id}) "${sourceElement.getDisplayLabel()}"`);
350
- const targetElementProps = await this.context.cloneElement(sourceElement, { binaryGeometry: this._options.cloneUsingBinaryGeometry });
355
+ const targetElementProps = await this._cloneContext.cloneElement(sourceElement, {
356
+ binaryGeometry: this._options.cloneUsingBinaryGeometry,
357
+ });
351
358
  // Special case: source element is the root subject
352
359
  if (sourceElement.id === core_common_1.IModel.rootSubjectId) {
353
360
  const targetElementId = this.context.findTargetElementId(sourceElement.id);
@@ -592,7 +599,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
592
599
  message: "The root Subject should not be directly imported",
593
600
  });
594
601
  }
595
- return this.exporter.exportElement(sourceElementId);
602
+ return this.processScopedElementExport(async () => this.exporter.exportElement(sourceElementId));
596
603
  }
597
604
  /** Import child elements into the target IModelDb
598
605
  * @param sourceElementId Import the child elements of this element in the source IModelDb.
@@ -600,7 +607,10 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
600
607
  */
601
608
  async processChildElements(sourceElementId) {
602
609
  await this.initialize();
603
- return this.exporter.exportChildElements(sourceElementId);
610
+ return this.processScopedElementExport(async () => this.exporter.exportChildElements(sourceElementId));
611
+ }
612
+ async processScopedElementExport(exportElements) {
613
+ await this.exporter.elementAspectExportCoordinator.run(exportElements);
604
614
  }
605
615
  /** Override of [IModelExportHandler.shouldExportElement]($transformer) that is called to determine if an element should be exported from the source iModel.
606
616
  * @note Reaching this point means that the element has passed the standard exclusion checks in IModelExporter.
@@ -927,7 +937,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
927
937
  */
928
938
  async processModel(sourceModeledElementId) {
929
939
  await this.initialize();
930
- return this.exporter.exportModel(sourceModeledElementId);
940
+ return this.processScopedElementExport(async () => this.exporter.exportModel(sourceModeledElementId));
931
941
  }
932
942
  /** Cause the model contents to be exported from the source iModel and imported into the target iModel.
933
943
  * @param sourceModelId Import the contents of this model from the source IModelDb.
@@ -939,7 +949,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
939
949
  await this.initialize();
940
950
  this.targetDb.models.getModel(targetModelId); // throws if Model does not exist
941
951
  this.context.remapElement(sourceModelId, targetModelId); // set remapping in case importModelContents is called directly
942
- return this.exporter.exportModelContents(sourceModelId, elementClassFullName);
952
+ return this.processScopedElementExport(async () => this.exporter.exportModelContents(sourceModelId, elementClassFullName));
943
953
  }
944
954
  /** Cause all sub-models that recursively descend from the specified Subject to be exported from the source iModel and imported into the target iModel. */
945
955
  async processSubjectSubModels(sourceSubjectId) {
@@ -1107,10 +1117,24 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1107
1117
  return targetRelationshipProps;
1108
1118
  }
1109
1119
  async shouldExportElementAspect(aspect) {
1110
- // This override is needed to ensure that aspects are not exported if their element is not exported.
1111
- // This is needed in case DetachedExportElementAspectsStrategy is used.
1120
+ // An aspect cannot be exported when its owner has no source-to-target
1121
+ // mapping.
1112
1122
  return this.context.findTargetElementId(aspect.element.id) !== core_bentley_1.Id64.invalid;
1113
1123
  }
1124
+ async prepareElementAspects(excludedElementAspectClassFullNames, elementIds) {
1125
+ if (!this.exporter.visitElements)
1126
+ return;
1127
+ if (elementIds === undefined)
1128
+ return;
1129
+ const targetElementIds = new Set();
1130
+ for (const sourceElementId of elementIds) {
1131
+ const targetElementId = this.context.findTargetElementId(sourceElementId);
1132
+ if (core_bentley_1.Id64.isValid(targetElementId)) {
1133
+ targetElementIds.add(targetElementId);
1134
+ }
1135
+ }
1136
+ await this.importer.elementAspectCleanup.delete(targetElementIds, excludedElementAspectClassFullNames, this.targetScopeElementId);
1137
+ }
1114
1138
  /** Override of [IModelExportHandler.onExportElementUniqueAspect]($transformer) that imports an ElementUniqueAspect into the target iModel when it is exported from the source iModel.
1115
1139
  * This override calls [[onTransformElementAspect]] and then [IModelImporter.importElementUniqueAspect]($transformer) to update the target iModel.
1116
1140
  */
@@ -1151,7 +1175,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1151
1175
  * @note A subclass can override this method to provide custom transform behavior.
1152
1176
  */
1153
1177
  async onTransformElementAspect(sourceElementAspect) {
1154
- const targetElementAspectProps = await this.context.cloneElementAspect(sourceElementAspect);
1178
+ const targetElementAspectProps = await this._cloneContext.cloneElementAspect(sourceElementAspect);
1155
1179
  return targetElementAspectProps;
1156
1180
  }
1157
1181
  /** The directory where schemas will be exported, a random temporary directory */
@@ -1246,7 +1270,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1246
1270
  }
1247
1271
  /** Override of [IModelExportHandler.onExportFont]($transformer) that imports a font into the target iModel when it is exported from the source iModel. */
1248
1272
  async onExportFont(font, _isUpdate) {
1249
- this.context.importFont(font.id);
1273
+ this._cloneContext.importFont(font.id);
1250
1274
  }
1251
1275
  /** Cause all CodeSpecs to be exported from the source iModel and imported into the target iModel.
1252
1276
  * @note This method is called from [[process]], so it only needs to be called directly when processing a subset of an iModel.
@@ -1270,7 +1294,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1270
1294
  }
1271
1295
  /** Override of [IModelExportHandler.onExportCodeSpec]($transformer) that imports a CodeSpec into the target iModel when it is exported from the source iModel. */
1272
1296
  async onExportCodeSpec(sourceCodeSpec) {
1273
- this.context.importCodeSpec(sourceCodeSpec.id);
1297
+ this._cloneContext.importCodeSpec(sourceCodeSpec.id);
1274
1298
  }
1275
1299
  /** Recursively import all Elements and sub-Models that descend from the specified Subject */
1276
1300
  async processSubject(sourceSubjectId, targetSubjectId) {
@@ -1278,8 +1302,10 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1278
1302
  this.sourceDb.elements.getElement(sourceSubjectId, core_backend_1.Subject); // throws if sourceSubjectId is not a Subject
1279
1303
  this.targetDb.elements.getElement(targetSubjectId, core_backend_1.Subject); // throws if targetSubjectId is not a Subject
1280
1304
  this.context.remapElement(sourceSubjectId, targetSubjectId);
1281
- await this.processChildElements(sourceSubjectId);
1282
- await this.processSubjectSubModels(sourceSubjectId);
1305
+ await this.processScopedElementExport(async () => {
1306
+ await this.processChildElements(sourceSubjectId);
1307
+ await this.processSubjectSubModels(sourceSubjectId);
1308
+ });
1283
1309
  await this.completePartiallyCommittedElements();
1284
1310
  await this.completePartiallyCommittedAspects();
1285
1311
  }
@@ -1301,7 +1327,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1301
1327
  this.assertEditTxnActive();
1302
1328
  await this.initScopeProvenance();
1303
1329
  await this._tryInitChangesetData(this._options.argsForProcessChanges);
1304
- await this.context.initialize();
1330
+ await this._cloneContext.initialize();
1305
1331
  const exporterInitOptions = await this.getExportInitOpts(this._options.argsForProcessChanges ?? {});
1306
1332
  await this.initializeChangesetScanAndExporter(exporterInitOptions);
1307
1333
  // Exporter must be initialized prior to processing changesets in order to properly handle entity recreations (an entity delete followed by an insert of that same entity).
@@ -1653,17 +1679,18 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
1653
1679
  this._sourceChangeDataState = "has-changes";
1654
1680
  await this.exporter.exportCodeSpecs();
1655
1681
  await this.exporter.exportFonts();
1656
- if (this._options.skipPropagateChangesToRootElements) {
1657
- // The RepositoryModel and root Subject of the target iModel should not be transformed.
1658
- await this.exporter.exportChildElements(core_common_1.IModel.rootSubjectId); // start below the root Subject
1659
- await this.exporter.exportModelContents(core_common_1.IModel.repositoryModelId, core_backend_1.Element.classFullName, true); // after the Subject hierarchy, process the other elements of the RepositoryModel
1660
- await this.exporter.exportSubModels(core_common_1.IModel.repositoryModelId); // start below the RepositoryModel
1661
- }
1662
- else {
1663
- await this.exporter.exportModel(core_common_1.IModel.repositoryModelId);
1664
- }
1665
- await this.completePartiallyCommittedElements();
1666
- await this.exporter["exportAllAspects"](); // eslint-disable-line @typescript-eslint/dot-notation
1682
+ await this.exporter.elementAspectExportCoordinator.run(async () => {
1683
+ if (this._options.skipPropagateChangesToRootElements) {
1684
+ // The RepositoryModel and root Subject of the target iModel should not be transformed.
1685
+ await this.exporter.exportChildElements(core_common_1.IModel.rootSubjectId); // start below the root Subject
1686
+ await this.exporter.exportModelContents(core_common_1.IModel.repositoryModelId, core_backend_1.Element.classFullName, true); // after the Subject hierarchy, process the other elements of the RepositoryModel
1687
+ await this.exporter.exportSubModels(core_common_1.IModel.repositoryModelId); // start below the RepositoryModel
1688
+ }
1689
+ else {
1690
+ await this.exporter.exportModel(core_common_1.IModel.repositoryModelId);
1691
+ }
1692
+ await this.completePartiallyCommittedElements();
1693
+ });
1667
1694
  await this.completePartiallyCommittedAspects();
1668
1695
  await this.exporter.exportRelationships(core_backend_1.ElementRefersToElements.classFullName);
1669
1696
  if (this._options.forceExternalSourceAspectProvenance &&