@itwin/imodel-transformer 1.0.0-dev.9 → 1.0.1-customchanges.0
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.
- package/CHANGELOG.md +29 -1
- package/README.md +17 -0
- package/lib/cjs/BranchProvenanceInitializer.d.ts.map +1 -1
- package/lib/cjs/BranchProvenanceInitializer.js +2 -0
- package/lib/cjs/BranchProvenanceInitializer.js.map +1 -1
- package/lib/cjs/EntityUnifier.d.ts +1 -1
- package/lib/cjs/IModelExporter.d.ts +100 -11
- package/lib/cjs/IModelExporter.d.ts.map +1 -1
- package/lib/cjs/IModelExporter.js +160 -29
- package/lib/cjs/IModelExporter.js.map +1 -1
- package/lib/cjs/IModelImporter.d.ts +26 -3
- package/lib/cjs/IModelImporter.d.ts.map +1 -1
- package/lib/cjs/IModelImporter.js +58 -20
- package/lib/cjs/IModelImporter.js.map +1 -1
- package/lib/cjs/IModelTransformer.d.ts +119 -140
- package/lib/cjs/IModelTransformer.d.ts.map +1 -1
- package/lib/cjs/IModelTransformer.js +388 -366
- package/lib/cjs/IModelTransformer.js.map +1 -1
- package/lib/cjs/{transformer.d.ts → imodel-transformer.d.ts} +1 -1
- package/lib/cjs/imodel-transformer.d.ts.map +1 -0
- package/lib/cjs/{transformer.js → imodel-transformer.js} +11 -2
- package/lib/cjs/imodel-transformer.js.map +1 -0
- package/package.json +6 -5
- package/lib/cjs/PendingReferenceMap.d.ts +0 -37
- package/lib/cjs/PendingReferenceMap.d.ts.map +0 -1
- package/lib/cjs/PendingReferenceMap.js +0 -92
- package/lib/cjs/PendingReferenceMap.js.map +0 -1
- package/lib/cjs/transformer.d.ts.map +0 -1
- package/lib/cjs/transformer.js.map +0 -1
|
@@ -55,7 +55,9 @@ class IModelExportHandler {
|
|
|
55
55
|
shouldExportElement(_element) {
|
|
56
56
|
return true;
|
|
57
57
|
}
|
|
58
|
-
/** Called when element is skipped instead of exported.
|
|
58
|
+
/** Called when element is skipped instead of exported.
|
|
59
|
+
* @note When an element is skipped, exporter will not export any of its child elements. Because of this, [[onSkipElement]] will not be invoked for any children of a "skipped" element.
|
|
60
|
+
*/
|
|
59
61
|
onSkipElement(_elementId) { }
|
|
60
62
|
/** Called when an element should be exported.
|
|
61
63
|
* @param element The element to export
|
|
@@ -130,7 +132,7 @@ exports.IModelExportHandler = IModelExportHandler;
|
|
|
130
132
|
class IModelExporter {
|
|
131
133
|
/**
|
|
132
134
|
* Retrieve the cached entity change information.
|
|
133
|
-
* @note This will only be initialized after [IModelExporter.exportChanges] is invoked.
|
|
135
|
+
* @note This will only be initialized after [IModelExporter.exportChanges] is invoked or [IModelExporter.initialize] is called.
|
|
134
136
|
*/
|
|
135
137
|
get sourceDbChanges() {
|
|
136
138
|
return this._sourceDbChanges;
|
|
@@ -214,6 +216,16 @@ class IModelExporter {
|
|
|
214
216
|
return;
|
|
215
217
|
this._exportElementAspectsStrategy.setAspectChanges(this._sourceDbChanges.aspect);
|
|
216
218
|
}
|
|
219
|
+
/**
|
|
220
|
+
* This function is called by the transformer as it is about to process the changesets passed to it in [[IModelTransformOptions.argsForProcessChanges]].
|
|
221
|
+
* This would be after the exporter has already processed the same set of changesets passed to the transformer in [[IModelTransformOptions.argsForProcessChanges]].
|
|
222
|
+
* This function should be used to modify the exporter's sourceDbChanges, if necessary, using [[ChangedInstanceIds.addCustomChange]]. See [[ChangedInstanceIds.addCustomChange]] for more information.
|
|
223
|
+
* @note [[IModelExporter.sourceDbChanges]] will only be defined if the transformer was called with [[IModelTransformOptions.argsForProcessChanges]].
|
|
224
|
+
* @note If defined, sourceDbChanges will already be populated with the changesets passed to the transformer, if any when this function is called by the transformer.
|
|
225
|
+
* @note The transformer will have built up the remap table between the source and target iModels before calling this function. This means that functions like [[IModelTransformer.context.findTargetElementId]] will return meaningful results.
|
|
226
|
+
* @note Its expected that this function be overridden by a subclass of exporter if it needs to modify sourceDbChanges.
|
|
227
|
+
*/
|
|
228
|
+
addCustomChanges() { }
|
|
217
229
|
/** Register the handler that will be called by IModelExporter. */
|
|
218
230
|
registerHandler(handler) {
|
|
219
231
|
this._handler = handler;
|
|
@@ -252,19 +264,25 @@ class IModelExporter {
|
|
|
252
264
|
await this.exportModel(core_common_1.IModel.repositoryModelId);
|
|
253
265
|
await this.exportRelationships(core_backend_1.ElementRefersToElements.classFullName);
|
|
254
266
|
}
|
|
255
|
-
|
|
267
|
+
/** Export changes from the source iModel.
|
|
268
|
+
* Inserts, updates, and deletes are determined by inspecting the changeset(s).
|
|
269
|
+
* @note To form a range of versions to process, set `startChangesetId` for the start (inclusive) of the desired
|
|
270
|
+
* range and open the source iModel as of the end (inclusive) of the desired range.
|
|
271
|
+
* @note the changedInstanceIds are just for this call to exportChanges, so you must continue to pass it in
|
|
272
|
+
* for consecutive calls
|
|
273
|
+
*/
|
|
274
|
+
async exportChanges(args) {
|
|
256
275
|
if (!this.sourceDb.isBriefcaseDb())
|
|
257
276
|
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, "Must be a briefcase to export changes");
|
|
258
277
|
if ("" === this.sourceDb.changeset.id) {
|
|
259
278
|
await this.exportAll(); // no changesets, so revert to exportAll
|
|
260
279
|
return;
|
|
261
280
|
}
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
};
|
|
281
|
+
const startChangeset = // TODO: This is weird.. why is this needed? I suspect we can remove this and just pass args to initialize?
|
|
282
|
+
args && "startChangeset" in args ? args.startChangeset : undefined;
|
|
283
|
+
const initOpts = {
|
|
284
|
+
startChangeset: { id: startChangeset?.id },
|
|
285
|
+
};
|
|
268
286
|
await this.initialize(initOpts);
|
|
269
287
|
// _sourceDbChanges are initialized in this.initialize
|
|
270
288
|
nodeAssert(this._sourceDbChanges !== undefined, "sourceDbChanges must be initialized.");
|
|
@@ -377,7 +395,7 @@ class IModelExporter {
|
|
|
377
395
|
async exportCodeSpecByName(codeSpecName) {
|
|
378
396
|
const codeSpec = this.sourceDb.codeSpecs.getByName(codeSpecName);
|
|
379
397
|
let isUpdate;
|
|
380
|
-
if (
|
|
398
|
+
if (this._sourceDbChanges !== undefined) {
|
|
381
399
|
// is changeset information available?
|
|
382
400
|
if (this._sourceDbChanges.codeSpec.insertIds.has(codeSpec.id)) {
|
|
383
401
|
isUpdate = false;
|
|
@@ -469,7 +487,7 @@ class IModelExporter {
|
|
|
469
487
|
/** Export the model (the container only) from the source iModel. */
|
|
470
488
|
async exportModelContainer(model) {
|
|
471
489
|
let isUpdate;
|
|
472
|
-
if (
|
|
490
|
+
if (this._sourceDbChanges !== undefined) {
|
|
473
491
|
// is changeset information available?
|
|
474
492
|
if (this._sourceDbChanges.model.insertIds.has(model.id)) {
|
|
475
493
|
isUpdate = false;
|
|
@@ -500,7 +518,7 @@ class IModelExporter {
|
|
|
500
518
|
core_bentley_1.Logger.logTrace(loggerCategory, `visitElements=false, skipping exportModelContents(${modelId})`);
|
|
501
519
|
return;
|
|
502
520
|
}
|
|
503
|
-
if (
|
|
521
|
+
if (this._sourceDbChanges !== undefined) {
|
|
504
522
|
// is changeset information available?
|
|
505
523
|
if (!this._sourceDbChanges.model.insertIds.has(modelId) &&
|
|
506
524
|
!this._sourceDbChanges.model.updateIds.has(modelId)) {
|
|
@@ -674,7 +692,7 @@ class IModelExporter {
|
|
|
674
692
|
return;
|
|
675
693
|
}
|
|
676
694
|
let isUpdate;
|
|
677
|
-
if (
|
|
695
|
+
if (this._sourceDbChanges !== undefined) {
|
|
678
696
|
// is changeset information available?
|
|
679
697
|
if (this._sourceDbChanges.relationship.insertIds.has(relInstanceId)) {
|
|
680
698
|
isUpdate = false;
|
|
@@ -711,7 +729,7 @@ class IModelExporter {
|
|
|
711
729
|
}
|
|
712
730
|
exports.IModelExporter = IModelExporter;
|
|
713
731
|
/** Class for holding change information.
|
|
714
|
-
* @
|
|
732
|
+
* @public
|
|
715
733
|
*/
|
|
716
734
|
class ChangedInstanceOps {
|
|
717
735
|
constructor() {
|
|
@@ -730,11 +748,16 @@ class ChangedInstanceOps {
|
|
|
730
748
|
val.delete.forEach((id) => this.deleteIds.add(id));
|
|
731
749
|
}
|
|
732
750
|
}
|
|
751
|
+
get isEmpty() {
|
|
752
|
+
return (0 === this.insertIds.size &&
|
|
753
|
+
0 === this.updateIds.size &&
|
|
754
|
+
0 === this.deleteIds.size);
|
|
755
|
+
}
|
|
733
756
|
}
|
|
734
757
|
exports.ChangedInstanceOps = ChangedInstanceOps;
|
|
735
758
|
/**
|
|
736
759
|
* Class for discovering modified elements between 2 versions of an iModel.
|
|
737
|
-
* @
|
|
760
|
+
* @public
|
|
738
761
|
*/
|
|
739
762
|
class ChangedInstanceIds {
|
|
740
763
|
constructor(db) {
|
|
@@ -745,6 +768,8 @@ class ChangedInstanceIds {
|
|
|
745
768
|
this.relationship = new ChangedInstanceOps();
|
|
746
769
|
this.font = new ChangedInstanceOps();
|
|
747
770
|
this._db = db;
|
|
771
|
+
this._hasCustomChanges = false;
|
|
772
|
+
this._entityReferenceToCustomDataMap = new Map();
|
|
748
773
|
}
|
|
749
774
|
async setupECClassIds() {
|
|
750
775
|
this._codeSpecSubclassIds = new Set();
|
|
@@ -752,9 +777,12 @@ class ChangedInstanceIds {
|
|
|
752
777
|
this._elementSubclassIds = new Set();
|
|
753
778
|
this._aspectSubclassIds = new Set();
|
|
754
779
|
this._relationshipSubclassIds = new Set();
|
|
780
|
+
this._relationshipSubclassIdsToSkip = new Set();
|
|
781
|
+
this._ecClassIdsToClassFullNames = new Map();
|
|
755
782
|
const addECClassIdsToSet = async (setToModify, baseClass) => {
|
|
756
|
-
for await (const row of this._db.createQueryReader(`SELECT ECInstanceId FROM ECDbMeta.ECClassDef
|
|
757
|
-
setToModify.add(row.
|
|
783
|
+
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})`)) {
|
|
784
|
+
setToModify.add(row.ECClassId);
|
|
785
|
+
this._ecClassIdsToClassFullNames?.set(row.ECClassId, `${row.schemaName}:${row.className}`);
|
|
758
786
|
}
|
|
759
787
|
};
|
|
760
788
|
const promises = [
|
|
@@ -764,6 +792,7 @@ class ChangedInstanceIds {
|
|
|
764
792
|
addECClassIdsToSet(this._aspectSubclassIds, "BisCore.ElementUniqueAspect"),
|
|
765
793
|
addECClassIdsToSet(this._aspectSubclassIds, "BisCore.ElementMultiAspect"),
|
|
766
794
|
addECClassIdsToSet(this._relationshipSubclassIds, "BisCore.ElementRefersToElements"),
|
|
795
|
+
addECClassIdsToSet(this._relationshipSubclassIdsToSkip, "BisCore.ElementDrivesElement"),
|
|
767
796
|
];
|
|
768
797
|
await Promise.all(promises);
|
|
769
798
|
}
|
|
@@ -772,7 +801,8 @@ class ChangedInstanceIds {
|
|
|
772
801
|
this._modelSubclassIds &&
|
|
773
802
|
this._elementSubclassIds &&
|
|
774
803
|
this._aspectSubclassIds &&
|
|
775
|
-
this._relationshipSubclassIds
|
|
804
|
+
this._relationshipSubclassIds &&
|
|
805
|
+
this._relationshipSubclassIdsToSkip);
|
|
776
806
|
}
|
|
777
807
|
isRelationship(ecClassId) {
|
|
778
808
|
return this._relationshipSubclassIds?.has(ecClassId);
|
|
@@ -789,6 +819,17 @@ class ChangedInstanceIds {
|
|
|
789
819
|
isElement(ecClassId) {
|
|
790
820
|
return this._elementSubclassIds?.has(ecClassId);
|
|
791
821
|
}
|
|
822
|
+
get hasCustomChanges() {
|
|
823
|
+
return this._hasCustomChanges;
|
|
824
|
+
}
|
|
825
|
+
get isEmpty() {
|
|
826
|
+
return (this.codeSpec.isEmpty &&
|
|
827
|
+
this.model.isEmpty &&
|
|
828
|
+
this.element.isEmpty &&
|
|
829
|
+
this.aspect.isEmpty &&
|
|
830
|
+
this.relationship.isEmpty &&
|
|
831
|
+
this.font.isEmpty);
|
|
832
|
+
}
|
|
792
833
|
/**
|
|
793
834
|
* 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.
|
|
794
835
|
* 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'
|
|
@@ -804,6 +845,8 @@ class ChangedInstanceIds {
|
|
|
804
845
|
const changeType = change.$meta?.op;
|
|
805
846
|
if (changeType === undefined)
|
|
806
847
|
throw new Error(`ChangeType was undefined for id: ${change.ECInstanceId}.`);
|
|
848
|
+
if (this._relationshipSubclassIdsToSkip?.has(ecClassId))
|
|
849
|
+
return;
|
|
807
850
|
if (this.isRelationship(ecClassId))
|
|
808
851
|
this.handleChange(this.relationship, changeType, change.ECInstanceId);
|
|
809
852
|
else if (this.isCodeSpec(ecClassId))
|
|
@@ -815,6 +858,104 @@ class ChangedInstanceIds {
|
|
|
815
858
|
else if (this.isElement(ecClassId))
|
|
816
859
|
this.handleChange(this.element, changeType, change.ECInstanceId);
|
|
817
860
|
}
|
|
861
|
+
/**
|
|
862
|
+
* Adds the provided change to the element changes maintained by this instance of ChangedInstanceIds
|
|
863
|
+
* 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'
|
|
864
|
+
* from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
|
|
865
|
+
* @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.
|
|
866
|
+
* @note It is the responsibility of the caller to ensure that the provided id is, in fact an element.
|
|
867
|
+
* @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.
|
|
868
|
+
*/
|
|
869
|
+
addCustomElementChange(changeType, id // TODO: Support bulk adds
|
|
870
|
+
) {
|
|
871
|
+
// if delete unnecessary?
|
|
872
|
+
this.addModelToUpdated(id);
|
|
873
|
+
this.handleChange(this.element, changeType, id);
|
|
874
|
+
}
|
|
875
|
+
/**
|
|
876
|
+
* Adds the provided change to the codespec changes maintained by this instance of ChangedInstanceIds
|
|
877
|
+
* 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'
|
|
878
|
+
* from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
|
|
879
|
+
* @note It is the responsibility of the caller to ensure that the provided id is, in fact a codespec.
|
|
880
|
+
* @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.
|
|
881
|
+
*/
|
|
882
|
+
addCustomCodeSpecChange(changeType, id) {
|
|
883
|
+
this.handleChange(this.codeSpec, changeType, id);
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Adds the provided change to the model changes maintained by this instance of ChangedInstanceIds
|
|
887
|
+
* 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'
|
|
888
|
+
* from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
|
|
889
|
+
* @note It is the responsibility of the caller to ensure that the provided id is, in fact a model.
|
|
890
|
+
* @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.
|
|
891
|
+
*/
|
|
892
|
+
addCustomModelChange(changeType, id) {
|
|
893
|
+
this.handleChange(this.model, changeType, id);
|
|
894
|
+
}
|
|
895
|
+
/**
|
|
896
|
+
* Adds the provided change to the aspect changes maintained by this instance of ChangedInstanceIds
|
|
897
|
+
* 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'
|
|
898
|
+
* from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
|
|
899
|
+
* @note It is the responsibility of the caller to ensure that the provided id is, in fact an aspect.
|
|
900
|
+
* @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.
|
|
901
|
+
*/
|
|
902
|
+
addCustomAspectChange(changeType, id) {
|
|
903
|
+
this.handleChange(this.aspect, changeType, id);
|
|
904
|
+
}
|
|
905
|
+
/**
|
|
906
|
+
* TODO: Think more about permutations of model updated / inserted / deleted. Can you delete a model without deleting its elements?
|
|
907
|
+
* What if model delete but custom change si to insert element into target?
|
|
908
|
+
* // It is possible and apparently occasionally sensical to delete a model without deleting its underlying element.
|
|
909
|
+
// - If only the model is deleted, [[initFromExternalSourceAspects]] will have already remapped the underlying element since it still exists.
|
|
910
|
+
// - If both were deleted, [[remapDeletedSourceEntities]] will find and remap the deleted element making this operation valid
|
|
911
|
+
* TODO: If the element is a custom delete we probably shouldnt be calling this?
|
|
912
|
+
* There is an optimization in [IModelExporter.exportModelContents] which doesn't try to export elements within a model unless the model itself is part of
|
|
913
|
+
* the sourceDbChanges. This method is used in addCustomChange to add the model to the updatedIds set so that the custom element changes are exported.
|
|
914
|
+
*/
|
|
915
|
+
addModelToUpdated(elementId) {
|
|
916
|
+
const modelId = this._db.elements.getElement(elementId).model;
|
|
917
|
+
this.handleChange(this.model, "Updated", modelId);
|
|
918
|
+
}
|
|
919
|
+
/** TODO: Maybe relationships only? maybe not. */
|
|
920
|
+
getCustomRelationshipDataFromId(id, type) {
|
|
921
|
+
if (type === "relationship") {
|
|
922
|
+
return this._entityReferenceToCustomDataMap.get(core_backend_1.EntityReferences.fromEntityType(id, core_common_1.ConcreteEntityTypes.Relationship));
|
|
923
|
+
}
|
|
924
|
+
return undefined;
|
|
925
|
+
}
|
|
926
|
+
/**
|
|
927
|
+
* Adds the provided change to the set of relationship changes maintained by this instance of ChangedInstanceIds.
|
|
928
|
+
* 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'
|
|
929
|
+
* from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
|
|
930
|
+
* @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.
|
|
931
|
+
* @throws if the ecClassId is NOT a relationship classId
|
|
932
|
+
* @param ecClassId class id of the custom change
|
|
933
|
+
* @param changeType insert, update or delete
|
|
934
|
+
* @param id ECInstanceID of the custom change
|
|
935
|
+
* @param sourceECInstanceId source ECInstanceId of the relationship
|
|
936
|
+
* @param targetECInstanceId target ECInstanceId of the relationship
|
|
937
|
+
*/
|
|
938
|
+
async addCustomRelationshipChange(ecClassId, changeType, id, sourceECInstanceId, targetECInstanceId) {
|
|
939
|
+
if (!this._ecClassIdsInitialized)
|
|
940
|
+
await this.setupECClassIds();
|
|
941
|
+
if (this._relationshipSubclassIdsToSkip?.has(ecClassId))
|
|
942
|
+
return;
|
|
943
|
+
if (!this._relationshipSubclassIds?.has(ecClassId))
|
|
944
|
+
throw new Error(`Misuse. id: ${id}, ecClassId: ${ecClassId} is not a relationship class. Use 'addCustomChange' instead.`);
|
|
945
|
+
this._hasCustomChanges = true;
|
|
946
|
+
const classFullName = this._ecClassIdsToClassFullNames?.get(ecClassId);
|
|
947
|
+
(0, core_bentley_1.assert)(classFullName !== undefined); // setupECClassIds adds an entry to the above map for every single ECClassId.
|
|
948
|
+
this._entityReferenceToCustomDataMap.set(core_backend_1.EntityReferences.fromEntityType(id, core_common_1.ConcreteEntityTypes.Relationship), {
|
|
949
|
+
sourceIdOfRelationship: sourceECInstanceId,
|
|
950
|
+
targetIdOfRelationship: targetECInstanceId,
|
|
951
|
+
ecClassId,
|
|
952
|
+
classFullName,
|
|
953
|
+
});
|
|
954
|
+
this.handleChange(this.relationship, changeType, id);
|
|
955
|
+
}
|
|
956
|
+
getClassFullNameFromECClassId(ecClassid) {
|
|
957
|
+
return this._ecClassIdsToClassFullNames?.get(ecClassid);
|
|
958
|
+
}
|
|
818
959
|
handleChange(changedInstanceOps, changeType, id) {
|
|
819
960
|
// if changeType is a delete and we already have the id in the inserts then we can remove the id from the inserts.
|
|
820
961
|
// if changeType is a delete and we already have the id in the updates then we can remove the id from the updates AND add it to the deletes.
|
|
@@ -839,12 +980,12 @@ class ChangedInstanceIds {
|
|
|
839
980
|
}
|
|
840
981
|
/**
|
|
841
982
|
* Initializes a new ChangedInstanceIds object with information taken from a range of changesets.
|
|
983
|
+
* @public
|
|
842
984
|
*/
|
|
843
985
|
static async initialize(opts) {
|
|
844
986
|
if ("changedInstanceIds" in opts)
|
|
845
987
|
return opts.changedInstanceIds;
|
|
846
988
|
const iModelId = opts.iModel.iModelId;
|
|
847
|
-
const accessToken = opts.accessToken;
|
|
848
989
|
const startChangeset = "startChangeset" in opts ? opts.startChangeset : undefined;
|
|
849
990
|
const changesetRanges = startChangeset !== undefined
|
|
850
991
|
? [
|
|
@@ -855,13 +996,11 @@ class ChangedInstanceIds {
|
|
|
855
996
|
changeset: {
|
|
856
997
|
id: startChangeset.id ?? opts.iModel.changeset.id,
|
|
857
998
|
},
|
|
858
|
-
accessToken,
|
|
859
999
|
})).index,
|
|
860
1000
|
opts.iModel.changeset.index ??
|
|
861
1001
|
(await core_backend_1.IModelHost.hubAccess.queryChangeset({
|
|
862
1002
|
iModelId,
|
|
863
1003
|
changeset: { id: opts.iModel.changeset.id },
|
|
864
|
-
accessToken,
|
|
865
1004
|
})).index,
|
|
866
1005
|
],
|
|
867
1006
|
]
|
|
@@ -870,7 +1009,6 @@ class ChangedInstanceIds {
|
|
|
870
1009
|
: undefined;
|
|
871
1010
|
const csFileProps = changesetRanges !== undefined
|
|
872
1011
|
? (await Promise.all(changesetRanges.map(async ([first, end]) => core_backend_1.IModelHost.hubAccess.downloadChangesets({
|
|
873
|
-
accessToken,
|
|
874
1012
|
iModelId,
|
|
875
1013
|
range: { first, end },
|
|
876
1014
|
targetDir: core_backend_1.BriefcaseManager.getChangeSetsPath(iModelId),
|
|
@@ -881,10 +1019,6 @@ class ChangedInstanceIds {
|
|
|
881
1019
|
if (csFileProps === undefined)
|
|
882
1020
|
return undefined;
|
|
883
1021
|
const changedInstanceIds = new ChangedInstanceIds(opts.iModel);
|
|
884
|
-
const relationshipECClassIdsToSkip = new Set();
|
|
885
|
-
for await (const row of opts.iModel.createQueryReader("SELECT ECInstanceId FROM ECDbMeta.ECClassDef where ECInstanceId IS (BisCore.ElementDrivesElement)")) {
|
|
886
|
-
relationshipECClassIdsToSkip.add(row.ECInstanceId);
|
|
887
|
-
}
|
|
888
1022
|
for (const csFile of csFileProps) {
|
|
889
1023
|
const csReader = core_backend_1.SqliteChangesetReader.openFile({
|
|
890
1024
|
fileName: csFile.pathname,
|
|
@@ -898,9 +1032,6 @@ class ChangedInstanceIds {
|
|
|
898
1032
|
}
|
|
899
1033
|
const changes = [...ecChangeUnifier.instances];
|
|
900
1034
|
for (const change of changes) {
|
|
901
|
-
if (change.ECClassId !== undefined &&
|
|
902
|
-
relationshipECClassIdsToSkip.has(change.ECClassId))
|
|
903
|
-
continue;
|
|
904
1035
|
await changedInstanceIds.addChange(change);
|
|
905
1036
|
}
|
|
906
1037
|
csReader.close();
|