@itwin/imodel-transformer 1.0.1-customchanges.3 → 1.0.1-customchanges.5

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.
@@ -254,7 +254,6 @@ export declare class IModelExporter {
254
254
  * range and open the source iModel as of the end (inclusive) of the desired range.
255
255
  * @note the changedInstanceIds are just for this call to exportChanges, so you must continue to pass it in
256
256
  * for consecutive calls
257
- * @note Passing {} or undefined to exportChanges will result in the current changeset of the source iModel being exported.
258
257
  */
259
258
  exportChanges(args?: ExportChangesOptions): Promise<void>;
260
259
  private _resetChangeDataOnExport;
@@ -347,19 +346,12 @@ export declare class ChangedInstanceOps {
347
346
  deleteIds: Set<string>;
348
347
  /** Initializes the object from IModelJsNative.ChangedInstanceOpsProps. */
349
348
  addFromJson(val: IModelJsNative.ChangedInstanceOpsProps | undefined): void;
349
+ /**
350
+ * Checks if empty.
351
+ * @returns true if there no ids in the ChangedInstanceOps object.
352
+ */
350
353
  get isEmpty(): boolean;
351
354
  }
352
- /**
353
- * Interface to describe a 'custom' change. A custom change is one which isn't found by reading changesets, but instead added by a user calling the 'addCustomChange' API on the ChangedInstanceIds instance.
354
- * The purpose a custom change would serve is to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
355
- * @beta
356
- */
357
- export interface ChangedInstanceCustomRelationshipData {
358
- sourceIdOfRelationship: Id64String;
359
- targetIdOfRelationship: Id64String;
360
- ecClassId: Id64String;
361
- classFullName: string;
362
- }
363
355
  /**
364
356
  * Class for discovering modified elements between 2 versions of an iModel.
365
357
  * @public
@@ -377,10 +369,6 @@ export declare class ChangedInstanceIds {
377
369
  private _aspectSubclassIds?;
378
370
  private _relationshipSubclassIds?;
379
371
  private _relationshipSubclassIdsToSkip?;
380
- private _ecClassIdsToClassFullNames?;
381
- /** c${string} is used to represent codeSpecs since they do not currently have a representation in the EntityReference class. This map holds information passed to the 'addCustom' functions. */
382
- private _entityReferenceToCustomDataMap;
383
- private _hasCustomRelationshipChanges;
384
372
  private _db;
385
373
  constructor(db: IModelDb);
386
374
  private setupECClassIds;
@@ -390,7 +378,9 @@ export declare class ChangedInstanceIds {
390
378
  private isAspect;
391
379
  private isModel;
392
380
  private isElement;
393
- get hasCustomRelationshipChanges(): boolean;
381
+ /** Checks if there are any changes.
382
+ * @returns true if there are any changes in the ChangedInstanceIds object.
383
+ */
394
384
  get hasChanges(): boolean;
395
385
  /**
396
386
  * Adds the provided [[ChangedECInstance]] to the appropriate set of changes by class type (codeSpec, model, element, aspect, or relationship) maintained by this instance of ChangedInstanceIds.
@@ -400,35 +390,32 @@ export declare class ChangedInstanceIds {
400
390
  */
401
391
  addChange(change: ChangedECInstance): Promise<void>;
402
392
  /**
403
- * Adds the provided change to the element changes maintained by this instance of ChangedInstanceIds
393
+ * This method should only be called inside [[IModelTransformer.addCustomChanges]].
394
+ * It adds the provided change to the element changes maintained by this instance of ChangedInstanceIds.
404
395
  * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
405
396
  * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
406
- * @note element changes will also cause the element's model to be marked as updated in [[ChangedInstanceIds.model]], so that the element does not get skipped by the transformer.
397
+ * @note Custom element 'Insert' and 'Update' will mark element's parent model hierarchy and their modeled elements as 'Updated' in [[ChangedInstanceIds.model]] and [[ChangedInstanceIds.element]]. Parent models have to be marked as 'Updated' to make sure that added change is not skipped by transformer. Transformer starts processing elements from RepositoryModel and then visits all child models. Modeled elements hierarchy is marked as updated to trigger their inserts in case a new model (or its parent) needs to be inserted.
398
+ * @note Custom element 'Insert' will also mark element aspects and all element relationships as inserted.
407
399
  * @note It is the responsibility of the caller to ensure that the provided id is, in fact an element.
408
400
  * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
401
+ * @note In data processing with filter criteria scenarios it is important to consistently filter out models and their modeled elements that were previously removed from target via [[addCustomModelChange]] or [[shouldExportElement]] apis.
409
402
  * @beta
410
403
  */
411
404
  addCustomElementChange(changeType: SqliteChangeOp, ids: Id64Arg): Promise<void>;
412
405
  /**
413
- * Adds the provided change to the codespec changes maintained by this instance of ChangedInstanceIds
414
- * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
415
- * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
416
- * @note It is the responsibility of the caller to ensure that the provided id is, in fact a codespec.
417
- * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
418
- * @beta
419
- */
420
- addCustomCodeSpecChange(changeType: SqliteChangeOp, ids: Id64Arg): void;
421
- /**
406
+ * This method should only be called inside [IModelTransformer.addCustomChanges].
422
407
  * Adds the provided change to the model changes maintained by this instance of ChangedInstanceIds.
423
- * Also adds the model's modeledElement to the element changes. This is to ensure the changes from the model and its modeledElement get exported together.
424
408
  * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
425
409
  * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
410
+ * Will add same change to the model's modeledElement by calling [[ChangedInstanceIds.addCustomElementChange]] which will register more needed changes. This is to ensure the changes from the model and its modeledElement get exported together.
426
411
  * @note It is the responsibility of the caller to ensure that the provided id is, in fact a model.
427
412
  * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
413
+ * @note In data processing with filter criteria scenarios it is important to consistently filter out models and their modeled elements that were previously removed from target via [[addCustomModelChange]] or [[shouldExportElement]] apis.
428
414
  * @beta
429
415
  */
430
416
  addCustomModelChange(changeType: SqliteChangeOp, ids: Id64Arg): Promise<void>;
431
417
  /**
418
+ * This method should only be called inside [IModelTransformer.addCustomChanges].
432
419
  * Adds the provided change to the aspect changes maintained by this instance of ChangedInstanceIds
433
420
  * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
434
421
  * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
@@ -438,34 +425,12 @@ export declare class ChangedInstanceIds {
438
425
  */
439
426
  addCustomAspectChange(changeType: SqliteChangeOp, ids: Id64Arg): void;
440
427
  /**
441
- * TODO: Think more about permutations of model updated / inserted / deleted. Can you delete a model without deleting its elements?
442
- * What if model delete but custom change si to insert element into target?
443
- * // It is possible and apparently occasionally sensical to delete a model without deleting its underlying element.
444
- // - If only the model is deleted, [[initFromExternalSourceAspects]] will have already remapped the underlying element since it still exists.
445
- // - If both were deleted, [[remapDeletedSourceEntities]] will find and remap the deleted element making this operation valid
446
- * TODO: If the element is a custom delete we probably shouldnt be calling this?
447
- * There is an optimization in [IModelExporter.exportModelContents] which doesn't try to export elements within a model unless the model itself is part of
448
- * the sourceDbChanges. This method is used in addCustomChange to add the model to the updatedIds set so that the custom element changes are exported.
449
- */
450
- private addModelsToUpdated;
451
- /** TODO: Maybe relationships only? maybe not.
452
- * @beta
453
- */
454
- getCustomRelationshipDataFromId(id: Id64String): ChangedInstanceCustomRelationshipData | undefined;
455
- /**
456
- * Adds the provided change to the set of relationship changes maintained by this instance of ChangedInstanceIds.
457
- * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
458
- * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
459
- * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
460
- * @throws if the ecClassId is NOT a relationship classId
461
- * @param ecClassId class id of the custom change
462
- * @param changeType insert, update or delete
463
- * @param id ECInstanceID of the custom change
464
- * @param sourceECInstanceId source ECInstanceId of the relationship
465
- * @param targetECInstanceId target ECInstanceId of the relationship
466
- * @beta
428
+ * There is an optimization in [IModelExporter.exportModelContents] which doesn't try to export elements within a model unless the model itself is marked as `Updated` or 'Inserted' in sourceDbChanges. This method is used in [[addCustomElementChange]] and [[addCustomModelChange]] to add the parent model hierarchy to the 'updatedIds' so that the custom element changes are exported.
429
+ * Transformer will insert 'Updated' model to target if it does not exist there already. To handle such case, modeled elements of parent models are also marked as updated. This is done, because model can not be inserted without it's modeled element.
467
430
  */
468
- addCustomRelationshipChange(ecClassId: string, changeType: SqliteChangeOp, id: Id64String, sourceECInstanceId: Id64String, targetECInstanceId: Id64String): Promise<void>;
431
+ private markParentModelsAsUpdated;
432
+ private markElementRelationshipsAsInserted;
433
+ private markElementAspectsAsInserted;
469
434
  private handleChange;
470
435
  /**
471
436
  * Initializes a new ChangedInstanceIds object with information taken from a range of changesets.
@@ -1 +1 @@
1
- {"version":3,"file":"IModelExporter.d.ts","sourceRoot":"","sources":["../../src/IModelExporter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"IModelExporter.d.ts","sourceRoot":"","sources":["../../src/IModelExporter.ts"],"names":[],"mappings":"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"}
@@ -260,7 +260,6 @@ class IModelExporter {
260
260
  * range and open the source iModel as of the end (inclusive) of the desired range.
261
261
  * @note the changedInstanceIds are just for this call to exportChanges, so you must continue to pass it in
262
262
  * for consecutive calls
263
- * @note Passing {} or undefined to exportChanges will result in the current changeset of the source iModel being exported.
264
263
  */
265
264
  async exportChanges(args) {
266
265
  if (!this.sourceDb.isBriefcaseDb())
@@ -269,17 +268,10 @@ class IModelExporter {
269
268
  await this.exportAll(); // no changesets, so revert to exportAll
270
269
  return;
271
270
  }
272
- const isEmptyObject = (obj) => Object.keys(obj).length === 0;
273
- let initOpts;
274
- if (args === undefined || isEmptyObject(args)) {
275
- // Fallback behavior for exportChanges with no args / empty object, this.initialize will process the current changeset of the source iModel being exported when startChangeset.id is undefined.
276
- initOpts = {
277
- startChangeset: { id: undefined },
278
- };
279
- }
280
- else {
281
- initOpts = args;
282
- }
271
+ const startChangeset = args && "startChangeset" in args ? args.startChangeset : undefined;
272
+ const initOpts = {
273
+ startChangeset: { id: startChangeset?.id },
274
+ };
283
275
  await this.initialize(initOpts);
284
276
  // _sourceDbChanges are initialized in this.initialize
285
277
  nodeAssert(this._sourceDbChanges !== undefined, "sourceDbChanges must be initialized.");
@@ -392,7 +384,7 @@ class IModelExporter {
392
384
  async exportCodeSpecByName(codeSpecName) {
393
385
  const codeSpec = this.sourceDb.codeSpecs.getByName(codeSpecName);
394
386
  let isUpdate;
395
- if (this._sourceDbChanges !== undefined) {
387
+ if (undefined !== this._sourceDbChanges) {
396
388
  // is changeset information available?
397
389
  if (this._sourceDbChanges.codeSpec.insertIds.has(codeSpec.id)) {
398
390
  isUpdate = false;
@@ -484,7 +476,7 @@ class IModelExporter {
484
476
  /** Export the model (the container only) from the source iModel. */
485
477
  async exportModelContainer(model) {
486
478
  let isUpdate;
487
- if (this._sourceDbChanges !== undefined) {
479
+ if (undefined !== this._sourceDbChanges) {
488
480
  // is changeset information available?
489
481
  if (this._sourceDbChanges.model.insertIds.has(model.id)) {
490
482
  isUpdate = false;
@@ -515,7 +507,7 @@ class IModelExporter {
515
507
  core_bentley_1.Logger.logTrace(loggerCategory, `visitElements=false, skipping exportModelContents(${modelId})`);
516
508
  return;
517
509
  }
518
- if (this._sourceDbChanges !== undefined) {
510
+ if (undefined !== this._sourceDbChanges) {
519
511
  // is changeset information available?
520
512
  if (!this._sourceDbChanges.model.insertIds.has(modelId) &&
521
513
  !this._sourceDbChanges.model.updateIds.has(modelId)) {
@@ -689,7 +681,7 @@ class IModelExporter {
689
681
  return;
690
682
  }
691
683
  let isUpdate;
692
- if (this._sourceDbChanges !== undefined) {
684
+ if (undefined !== this._sourceDbChanges) {
693
685
  // is changeset information available?
694
686
  if (this._sourceDbChanges.relationship.insertIds.has(relInstanceId)) {
695
687
  isUpdate = false;
@@ -745,6 +737,10 @@ class ChangedInstanceOps {
745
737
  val.delete.forEach((id) => this.deleteIds.add(id));
746
738
  }
747
739
  }
740
+ /**
741
+ * Checks if empty.
742
+ * @returns true if there no ids in the ChangedInstanceOps object.
743
+ */
748
744
  get isEmpty() {
749
745
  return (0 === this.insertIds.size &&
750
746
  0 === this.updateIds.size &&
@@ -765,8 +761,6 @@ class ChangedInstanceIds {
765
761
  this.relationship = new ChangedInstanceOps();
766
762
  this.font = new ChangedInstanceOps();
767
763
  this._db = db;
768
- this._hasCustomRelationshipChanges = false;
769
- this._entityReferenceToCustomDataMap = new Map();
770
764
  }
771
765
  async setupECClassIds() {
772
766
  this._codeSpecSubclassIds = new Set();
@@ -775,11 +769,9 @@ class ChangedInstanceIds {
775
769
  this._aspectSubclassIds = new Set();
776
770
  this._relationshipSubclassIds = new Set();
777
771
  this._relationshipSubclassIdsToSkip = new Set();
778
- this._ecClassIdsToClassFullNames = new Map();
779
772
  const addECClassIdsToSet = async (setToModify, baseClass) => {
780
- for await (const row of this._db.createQueryReader(`SELECT c.ECInstanceId ECClassId, c.Name className, s.Name schemaName FROM ECDbMeta.ECClassDef c JOIN ECDbMeta.ECSchemaDef s ON s.ECInstanceId = c.Schema.Id WHERE c.ECInstanceId IS (${baseClass})`)) {
781
- setToModify.add(row.ECClassId);
782
- this._ecClassIdsToClassFullNames?.set(row.ECClassId, `${row.schemaName}:${row.className}`);
773
+ for await (const row of this._db.createQueryReader(`SELECT ECInstanceId FROM ECDbMeta.ECClassDef where ECInstanceId IS (${baseClass})`)) {
774
+ setToModify.add(row.ECInstanceId);
783
775
  }
784
776
  };
785
777
  const promises = [
@@ -816,9 +808,9 @@ class ChangedInstanceIds {
816
808
  isElement(ecClassId) {
817
809
  return this._elementSubclassIds?.has(ecClassId);
818
810
  }
819
- get hasCustomRelationshipChanges() {
820
- return this._hasCustomRelationshipChanges;
821
- }
811
+ /** Checks if there are any changes.
812
+ * @returns true if there are any changes in the ChangedInstanceIds object.
813
+ */
822
814
  get hasChanges() {
823
815
  return (!this.codeSpec.isEmpty ||
824
816
  !this.model.isEmpty ||
@@ -856,41 +848,51 @@ class ChangedInstanceIds {
856
848
  this.handleChange(this.element, changeType, change.ECInstanceId);
857
849
  }
858
850
  /**
859
- * Adds the provided change to the element changes maintained by this instance of ChangedInstanceIds
851
+ * This method should only be called inside [[IModelTransformer.addCustomChanges]].
852
+ * It adds the provided change to the element changes maintained by this instance of ChangedInstanceIds.
860
853
  * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
861
854
  * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
862
- * @note element changes will also cause the element's model to be marked as updated in [[ChangedInstanceIds.model]], so that the element does not get skipped by the transformer.
855
+ * @note Custom element 'Insert' and 'Update' will mark element's parent model hierarchy and their modeled elements as 'Updated' in [[ChangedInstanceIds.model]] and [[ChangedInstanceIds.element]]. Parent models have to be marked as 'Updated' to make sure that added change is not skipped by transformer. Transformer starts processing elements from RepositoryModel and then visits all child models. Modeled elements hierarchy is marked as updated to trigger their inserts in case a new model (or its parent) needs to be inserted.
856
+ * @note Custom element 'Insert' will also mark element aspects and all element relationships as inserted.
863
857
  * @note It is the responsibility of the caller to ensure that the provided id is, in fact an element.
864
858
  * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
859
+ * @note In data processing with filter criteria scenarios it is important to consistently filter out models and their modeled elements that were previously removed from target via [[addCustomModelChange]] or [[shouldExportElement]] apis.
865
860
  * @beta
866
861
  */
867
862
  async addCustomElementChange(changeType, ids) {
868
- // if delete unnecessary?
869
- await this.addModelsToUpdated(ids);
863
+ if (core_bentley_1.Id64.sizeOf(ids) === 0) {
864
+ return;
865
+ }
870
866
  for (const id of core_bentley_1.Id64.iterable(ids)) {
871
867
  this.handleChange(this.element, changeType, id);
872
868
  }
873
- }
874
- /**
875
- * Adds the provided change to the codespec changes maintained by this instance of ChangedInstanceIds
876
- * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
877
- * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
878
- * @note It is the responsibility of the caller to ensure that the provided id is, in fact a codespec.
879
- * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
880
- * @beta
881
- */
882
- addCustomCodeSpecChange(changeType, ids) {
883
- for (const id of core_bentley_1.Id64.iterable(ids)) {
884
- this.handleChange(this.codeSpec, changeType, id);
869
+ if (changeType === "Deleted") {
870
+ return;
871
+ }
872
+ const idsSet = core_bentley_1.Id64.toIdSet(ids);
873
+ // Parent models have to be marked as 'Updated' to make sure that added change is not skipped by transformer. Transformer starts processing elements from RepositoryModel and then visits all child models.
874
+ // Transformer handles update as insert if element is not found in target, for this reason modeled elements will be also marked as updated to trigger their inserts in case a new model (or its parent) needs to be inserted. Otherwise error would be thrown about missing modeled element while inserting new model.
875
+ const parentModelIds = await this.markParentModelsAsUpdated(idsSet);
876
+ // Aspects and relationships of inserted data needs to be marked as inserted otherwise those would not be exported
877
+ if (changeType === "Inserted") {
878
+ // Adding parents as well as we are not sure if those were inserted or updated
879
+ parentModelIds.forEach((parentId) => {
880
+ idsSet.add(parentId);
881
+ });
882
+ await this.markElementAspectsAsInserted(idsSet);
883
+ // Marking only ElementRefersToElements.classFullName as only those are exported in exportRelationships()
884
+ await this.markElementRelationshipsAsInserted(core_backend_1.ElementRefersToElements.classFullName, idsSet);
885
885
  }
886
886
  }
887
887
  /**
888
+ * This method should only be called inside [IModelTransformer.addCustomChanges].
888
889
  * Adds the provided change to the model changes maintained by this instance of ChangedInstanceIds.
889
- * Also adds the model's modeledElement to the element changes. This is to ensure the changes from the model and its modeledElement get exported together.
890
890
  * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
891
891
  * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
892
+ * Will add same change to the model's modeledElement by calling [[ChangedInstanceIds.addCustomElementChange]] which will register more needed changes. This is to ensure the changes from the model and its modeledElement get exported together.
892
893
  * @note It is the responsibility of the caller to ensure that the provided id is, in fact a model.
893
894
  * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
895
+ * @note In data processing with filter criteria scenarios it is important to consistently filter out models and their modeled elements that were previously removed from target via [[addCustomModelChange]] or [[shouldExportElement]] apis.
894
896
  * @beta
895
897
  */
896
898
  async addCustomModelChange(changeType, ids) {
@@ -901,6 +903,7 @@ class ChangedInstanceIds {
901
903
  }
902
904
  }
903
905
  /**
906
+ * This method should only be called inside [IModelTransformer.addCustomChanges].
904
907
  * Adds the provided change to the aspect changes maintained by this instance of ChangedInstanceIds
905
908
  * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
906
909
  * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
@@ -914,58 +917,57 @@ class ChangedInstanceIds {
914
917
  }
915
918
  }
916
919
  /**
917
- * TODO: Think more about permutations of model updated / inserted / deleted. Can you delete a model without deleting its elements?
918
- * What if model delete but custom change si to insert element into target?
919
- * // It is possible and apparently occasionally sensical to delete a model without deleting its underlying element.
920
- // - If only the model is deleted, [[initFromExternalSourceAspects]] will have already remapped the underlying element since it still exists.
921
- // - If both were deleted, [[remapDeletedSourceEntities]] will find and remap the deleted element making this operation valid
922
- * TODO: If the element is a custom delete we probably shouldnt be calling this?
923
- * There is an optimization in [IModelExporter.exportModelContents] which doesn't try to export elements within a model unless the model itself is part of
924
- * the sourceDbChanges. This method is used in addCustomChange to add the model to the updatedIds set so that the custom element changes are exported.
920
+ * There is an optimization in [IModelExporter.exportModelContents] which doesn't try to export elements within a model unless the model itself is marked as `Updated` or 'Inserted' in sourceDbChanges. This method is used in [[addCustomElementChange]] and [[addCustomModelChange]] to add the parent model hierarchy to the 'updatedIds' so that the custom element changes are exported.
921
+ * Transformer will insert 'Updated' model to target if it does not exist there already. To handle such case, modeled elements of parent models are also marked as updated. This is done, because model can not be inserted without it's modeled element.
925
922
  */
926
- async addModelsToUpdated(elementIds) {
927
- const compressedIds = core_bentley_1.CompressedId64Set.sortAndCompress(core_bentley_1.Id64.iterable(elementIds));
928
- const params = new core_common_1.QueryBinder().bindIdSet("elementIds", core_bentley_1.CompressedId64Set.iterable(compressedIds));
929
- for await (const row of this._db.createQueryReader("SELECT Model.Id FROM BisCore.Element WHERE InVirtualSet(:elementIds, ECInstanceId)", params)) {
930
- this.handleChange(this.model, "Updated", row.id);
923
+ async markParentModelsAsUpdated(elementIds) {
924
+ const params = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
925
+ const ecQuery = `
926
+ WITH RECURSIVE hierarchy (parentId) AS (
927
+ SELECT Model.Id FROM bis.Element WHERE InVirtualSet(:elementIds, ECInstanceId)
928
+ UNION
929
+ SELECT ParentModel.id
930
+ FROM bis.Model e
931
+ INNER JOIN hierarchy h ON h.parentId = e.ECInstanceId
932
+ )
933
+ SELECT parentId FROM hierarchy where parentId is not null
934
+ `;
935
+ const parentModelIds = new Set();
936
+ for await (const row of this._db.createQueryReader(ecQuery, params)) {
937
+ // Transformer handles update as insert when element does not exist in target.
938
+ // Which means that in scenario where child and parent model are filtered out from target,
939
+ // and child element is inserted trough custom change, its parent model will be marked as updated.
940
+ // Transformer then will:
941
+ // 1. Handle parent update as insert (since it does not exist in target).
942
+ // 2. Will insert child element (otherwise this insert would be ignored due to missing parent).
943
+ this.handleChange(this.model, "Updated", row.parentId);
944
+ this.handleChange(this.element, "Updated", row.parentId);
945
+ parentModelIds.add(row.parentId);
931
946
  }
947
+ return parentModelIds;
932
948
  }
933
- /** TODO: Maybe relationships only? maybe not.
934
- * @beta
935
- */
936
- getCustomRelationshipDataFromId(id) {
937
- return this._entityReferenceToCustomDataMap.get(core_backend_1.EntityReferences.fromEntityType(id, core_common_1.ConcreteEntityTypes.Relationship));
949
+ async markElementRelationshipsAsInserted(relationshipClassName, elementIds) {
950
+ const ecQuery = `SELECT ECInstanceId FROM ${relationshipClassName}
951
+ WHERE InVirtualSet(:elementIds, TargetECInstanceId)
952
+ OR InVirtualSet(:elementIds, SourceECInstanceId)`;
953
+ const queryBinder = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
954
+ const queryReader = this._db.createQueryReader(ecQuery, queryBinder);
955
+ for await (const row of queryReader) {
956
+ this.handleChange(this.relationship, "Inserted", row.ECInstanceId);
957
+ }
938
958
  }
939
- /**
940
- * Adds the provided change to the set of relationship changes maintained by this instance of ChangedInstanceIds.
941
- * If the same ECInstanceId is seen multiple times, the changedInstanceIds will be modified accordingly, i.e. if an id 'x' was updated but now we see 'x' was deleted, we will remove 'x'
942
- * from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
943
- * @note In most cases, this method does not need to be called. Its only for consumers to mimic changes as if they were found in a changeset, which should only be useful in certain cases such as the changing of filter criteria for a preexisting master branch relationship.
944
- * @throws if the ecClassId is NOT a relationship classId
945
- * @param ecClassId class id of the custom change
946
- * @param changeType insert, update or delete
947
- * @param id ECInstanceID of the custom change
948
- * @param sourceECInstanceId source ECInstanceId of the relationship
949
- * @param targetECInstanceId target ECInstanceId of the relationship
950
- * @beta
951
- */
952
- async addCustomRelationshipChange(ecClassId, changeType, id, sourceECInstanceId, targetECInstanceId) {
953
- if (!this._ecClassIdsInitialized)
954
- await this.setupECClassIds();
955
- if (this._relationshipSubclassIdsToSkip?.has(ecClassId))
956
- return;
957
- if (!this._relationshipSubclassIds?.has(ecClassId))
958
- throw new Error(`Misuse. id: ${id}, ecClassId: ${ecClassId} is not a relationship class. Use 'addCustomChange' instead.`);
959
- this._hasCustomRelationshipChanges = true;
960
- const classFullName = this._ecClassIdsToClassFullNames?.get(ecClassId);
961
- (0, core_bentley_1.assert)(classFullName !== undefined); // setupECClassIds adds an entry to the above map for every single ECClassId.
962
- this._entityReferenceToCustomDataMap.set(core_backend_1.EntityReferences.fromEntityType(id, core_common_1.ConcreteEntityTypes.Relationship), {
963
- sourceIdOfRelationship: sourceECInstanceId,
964
- targetIdOfRelationship: targetECInstanceId,
965
- ecClassId,
966
- classFullName,
967
- });
968
- this.handleChange(this.relationship, changeType, id);
959
+ async markElementAspectsAsInserted(elementIds) {
960
+ for (const aspectClassName of [
961
+ core_backend_1.ElementUniqueAspect.classFullName,
962
+ core_backend_1.ElementMultiAspect.classFullName,
963
+ ]) {
964
+ const ecQuery = `Select ECInstanceId from ${aspectClassName} where InVirtualSet(:elementIds, Element.Id)`;
965
+ const queryBinder = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
966
+ const queryReader = this._db.createQueryReader(ecQuery, queryBinder);
967
+ for await (const row of queryReader) {
968
+ this.addCustomAspectChange("Inserted", row.toArray()[0]);
969
+ }
970
+ }
969
971
  }
970
972
  handleChange(changedInstanceOps, changeType, id) {
971
973
  // if changeType is a delete and we already have the id in the inserts then we can remove the id from the inserts.