@itwin/imodel-transformer 2.0.0-dev.4 → 2.0.0-dev.6
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/lib/cjs/BranchProvenanceInitializer.d.ts.map +1 -1
- package/lib/cjs/BranchProvenanceInitializer.js +1 -3
- package/lib/cjs/BranchProvenanceInitializer.js.map +1 -1
- package/lib/cjs/DetachedExportElementAspectsStrategy.d.ts.map +1 -1
- package/lib/cjs/DetachedExportElementAspectsStrategy.js +2 -2
- package/lib/cjs/DetachedExportElementAspectsStrategy.js.map +1 -1
- package/lib/cjs/ECReferenceTypesCache.d.ts.map +1 -1
- package/lib/cjs/ECReferenceTypesCache.js +4 -3
- package/lib/cjs/ECReferenceTypesCache.js.map +1 -1
- package/lib/cjs/ExportElementAspectsStrategy.d.ts +2 -2
- package/lib/cjs/ExportElementAspectsStrategy.d.ts.map +1 -1
- package/lib/cjs/ExportElementAspectsStrategy.js.map +1 -1
- package/lib/cjs/ExportElementAspectsWithElementsStrategy.js +2 -2
- package/lib/cjs/ExportElementAspectsWithElementsStrategy.js.map +1 -1
- package/lib/cjs/IModelCloneContext.d.ts +2 -2
- package/lib/cjs/IModelCloneContext.d.ts.map +1 -1
- package/lib/cjs/IModelCloneContext.js +38 -37
- package/lib/cjs/IModelCloneContext.js.map +1 -1
- package/lib/cjs/IModelExporter.d.ts +16 -7
- package/lib/cjs/IModelExporter.d.ts.map +1 -1
- package/lib/cjs/IModelExporter.js +78 -83
- package/lib/cjs/IModelExporter.js.map +1 -1
- package/lib/cjs/IModelImporter.d.ts +2 -2
- package/lib/cjs/IModelImporter.d.ts.map +1 -1
- package/lib/cjs/IModelImporter.js +10 -13
- package/lib/cjs/IModelImporter.js.map +1 -1
- package/lib/cjs/IModelTransformer.d.ts +13 -13
- package/lib/cjs/IModelTransformer.d.ts.map +1 -1
- package/lib/cjs/IModelTransformer.js +243 -265
- package/lib/cjs/IModelTransformer.js.map +1 -1
- package/package.json +1 -1
|
@@ -120,6 +120,26 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
120
120
|
AND Identifier=:identifier
|
|
121
121
|
LIMIT 1
|
|
122
122
|
`;
|
|
123
|
+
// if (aspectProps.scope === undefined) return undefined;
|
|
124
|
+
// const params = new QueryBinder().bindId("elementId", aspectProps.element.id);
|
|
125
|
+
// params.bindId("scopeId", aspectProps.scope.id);
|
|
126
|
+
// params.bindString("kind", aspectProps.kind);
|
|
127
|
+
// params.bindString("identifier", aspectProps.identifier);
|
|
128
|
+
// const result = await dbToQuery.createQueryReader(sql);
|
|
129
|
+
// if (result) {
|
|
130
|
+
// const aspectId = result.current.id;
|
|
131
|
+
// const versionValue = result.current[1];
|
|
132
|
+
// const version = versionValue.isNull
|
|
133
|
+
// ? undefined
|
|
134
|
+
// : versionValue.getString();
|
|
135
|
+
// const jsonPropsValue = result.current[2];
|
|
136
|
+
// const jsonProperties = jsonPropsValue.isNull
|
|
137
|
+
// ? undefined
|
|
138
|
+
// : jsonPropsValue.getString();
|
|
139
|
+
// return { aspectId, version, jsonProperties };
|
|
140
|
+
// }
|
|
141
|
+
// else
|
|
142
|
+
// return undefined;
|
|
123
143
|
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
124
144
|
return dbToQuery.withPreparedStatement(sql, (statement) => {
|
|
125
145
|
statement.bindId("elementId", aspectProps.element.id);
|
|
@@ -239,7 +259,6 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
239
259
|
// non-falsy defaults
|
|
240
260
|
cloneUsingBinaryGeometry: options?.cloneUsingBinaryGeometry ?? true,
|
|
241
261
|
targetScopeElementId: options?.targetScopeElementId ?? core_common_1.IModel.rootSubjectId,
|
|
242
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
243
262
|
danglingReferencesBehavior: options?.danglingReferencesBehavior ?? "reject",
|
|
244
263
|
branchRelationshipDataBehavior: options?.branchRelationshipDataBehavior ?? "reject",
|
|
245
264
|
skipPropagateChangesToRootElements: options?.skipPropagateChangesToRootElements ?? true,
|
|
@@ -332,7 +351,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
332
351
|
/** Dispose any native resources associated with this IModelTransformer. */
|
|
333
352
|
dispose() {
|
|
334
353
|
core_bentley_1.Logger.logTrace(loggerCategory, "dispose()");
|
|
335
|
-
this.context.dispose();
|
|
354
|
+
this.context[Symbol.dispose]();
|
|
336
355
|
}
|
|
337
356
|
/** Log current settings that affect IModelTransformer's behavior. */
|
|
338
357
|
logSettings() {
|
|
@@ -385,7 +404,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
385
404
|
};
|
|
386
405
|
return aspectProps;
|
|
387
406
|
}
|
|
388
|
-
static initRelationshipProvenanceOptions(sourceRelInstanceId, targetRelInstanceId, args) {
|
|
407
|
+
static async initRelationshipProvenanceOptions(sourceRelInstanceId, targetRelInstanceId, args) {
|
|
389
408
|
const provenanceDb = args.isReverseSynchronization
|
|
390
409
|
? args.sourceDb
|
|
391
410
|
: args.targetDb;
|
|
@@ -395,12 +414,13 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
395
414
|
const provenanceRelInstanceId = args.isReverseSynchronization
|
|
396
415
|
? sourceRelInstanceId
|
|
397
416
|
: targetRelInstanceId;
|
|
398
|
-
|
|
399
|
-
const
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
return stmt.getValue(0).getId();
|
|
417
|
+
const sql = "SELECT SourceECInstanceId FROM bis.ElementRefersToElements WHERE ECInstanceId=?";
|
|
418
|
+
const params = new core_common_1.QueryBinder().bindId(1, provenanceRelInstanceId);
|
|
419
|
+
const reader = provenanceDb.createQueryReader(sql, params, {
|
|
420
|
+
usePrimaryConn: true,
|
|
403
421
|
});
|
|
422
|
+
nodeAssert(await reader.step(), "relationship provenance query returned no rows");
|
|
423
|
+
const elementId = reader.current[0];
|
|
404
424
|
const jsonProperties = args.forceOldRelationshipProvenanceMethod
|
|
405
425
|
? { targetRelInstanceId }
|
|
406
426
|
: { provenanceRelInstanceId };
|
|
@@ -438,8 +458,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
438
458
|
* The `identifier` property of the ExternalSourceAspect will be the ECInstanceId of the relationship in the master iModel.
|
|
439
459
|
* The ECInstanceId of the relationship in the branch iModel will be stored in the JsonProperties of the ExternalSourceAspect.
|
|
440
460
|
*/
|
|
441
|
-
initRelationshipProvenance(sourceRelationship, targetRelInstanceId) {
|
|
442
|
-
return IModelTransformer.initRelationshipProvenanceOptions(sourceRelationship.id, targetRelInstanceId, {
|
|
461
|
+
async initRelationshipProvenance(sourceRelationship, targetRelInstanceId) {
|
|
462
|
+
return await IModelTransformer.initRelationshipProvenanceOptions(sourceRelationship.id, targetRelInstanceId, {
|
|
443
463
|
sourceDb: this.sourceDb,
|
|
444
464
|
targetDb: this.targetDb,
|
|
445
465
|
isReverseSynchronization: this.isReverseSynchronization,
|
|
@@ -517,7 +537,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
517
537
|
* @returns the last synced version (changesetId) on the target scope's external source aspect,
|
|
518
538
|
* if this was a [BriefcaseDb]($backend)
|
|
519
539
|
*/
|
|
520
|
-
initScopeProvenance() {
|
|
540
|
+
async initScopeProvenance() {
|
|
521
541
|
const aspectProps = {
|
|
522
542
|
id: undefined,
|
|
523
543
|
version: undefined,
|
|
@@ -548,15 +568,14 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
548
568
|
AND Kind=:kind
|
|
549
569
|
LIMIT 1
|
|
550
570
|
`;
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
//
|
|
554
|
-
(
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
statement.bindString("kind", aspectProps.kind);
|
|
558
|
-
return core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step();
|
|
571
|
+
const params = new core_common_1.QueryBinder();
|
|
572
|
+
params.bindId("elementId", aspectProps.element.id);
|
|
573
|
+
params.bindId("scopeId", aspectProps.scope.id); // this scope.id can never be invalid, we create it above
|
|
574
|
+
params.bindString("kind", aspectProps.kind);
|
|
575
|
+
const reader = this.provenanceDb.createQueryReader(sql, params, {
|
|
576
|
+
usePrimaryConn: true,
|
|
559
577
|
});
|
|
578
|
+
const hasConflictingScope = await reader.step();
|
|
560
579
|
if (hasConflictingScope) {
|
|
561
580
|
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.InvalidId, "Provenance scope conflict");
|
|
562
581
|
}
|
|
@@ -648,7 +667,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
648
667
|
* @note provenance is done by federation guids where possible
|
|
649
668
|
* @note this may execute on each element more than once! Only use in cases where that is handled
|
|
650
669
|
*/
|
|
651
|
-
static forEachTrackedElement(args) {
|
|
670
|
+
static async forEachTrackedElement(args) {
|
|
652
671
|
if (args.provenanceDb === args.provenanceSourceDb)
|
|
653
672
|
return;
|
|
654
673
|
if (!args.provenanceDb.containsClass(core_backend_1.ExternalSourceAspect.classFullName)) {
|
|
@@ -673,42 +692,28 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
673
692
|
// NOTE: if we exposed the native attach database support,
|
|
674
693
|
// we could get the intersection of fed guids in one query, not sure if it would be faster
|
|
675
694
|
// OR we could do a raw sqlite query...
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
if (
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
currSourceRow.federationGuid === currTargetRow.federationGuid) {
|
|
693
|
-
// data flow direction is always sourceDb -> targetDb and it does not depend on where the explicit element provenance is stored
|
|
694
|
-
args.fn(sourceRow.id, targetRow.id);
|
|
695
|
-
}
|
|
696
|
-
if (currTargetRow.federationGuid === undefined ||
|
|
697
|
-
(currSourceRow.federationGuid !== undefined &&
|
|
698
|
-
currSourceRow.federationGuid >= currTargetRow.federationGuid)) {
|
|
699
|
-
if (targetStmt.step() !== core_bentley_1.DbResult.BE_SQLITE_ROW)
|
|
700
|
-
return;
|
|
701
|
-
targetRow = targetStmt.getRow();
|
|
702
|
-
}
|
|
703
|
-
if (currSourceRow.federationGuid === undefined ||
|
|
704
|
-
(currTargetRow.federationGuid !== undefined &&
|
|
705
|
-
currSourceRow.federationGuid <= currTargetRow.federationGuid)) {
|
|
706
|
-
if (sourceStmt.step() !== core_bentley_1.DbResult.BE_SQLITE_ROW)
|
|
707
|
-
return;
|
|
708
|
-
sourceRow = sourceStmt.getRow();
|
|
709
|
-
}
|
|
695
|
+
const sourceReader = sourceDb.createQueryReader(elementIdByFedGuidQuery);
|
|
696
|
+
const targetReader = targetDb.createQueryReader(elementIdByFedGuidQuery);
|
|
697
|
+
let hasSourceRow = await sourceReader.step();
|
|
698
|
+
let hasTargetRow = await targetReader.step();
|
|
699
|
+
while (hasSourceRow && hasTargetRow) {
|
|
700
|
+
const sourceFedGuid = sourceReader.current.federationGuid;
|
|
701
|
+
const targetFedGuid = targetReader.current.federationGuid;
|
|
702
|
+
if (sourceFedGuid !== undefined &&
|
|
703
|
+
targetFedGuid !== undefined &&
|
|
704
|
+
sourceFedGuid === targetFedGuid) {
|
|
705
|
+
// data flow direction is always sourceDb -> targetDb and it does not depend on where the explicit element provenance is stored
|
|
706
|
+
args.fn(sourceReader.current.id, targetReader.current.id);
|
|
707
|
+
}
|
|
708
|
+
if (targetFedGuid === undefined ||
|
|
709
|
+
(sourceFedGuid !== undefined && sourceFedGuid >= targetFedGuid)) {
|
|
710
|
+
hasTargetRow = await targetReader.step();
|
|
710
711
|
}
|
|
711
|
-
|
|
712
|
+
if (sourceFedGuid === undefined ||
|
|
713
|
+
(targetFedGuid !== undefined && sourceFedGuid <= targetFedGuid)) {
|
|
714
|
+
hasSourceRow = await sourceReader.step();
|
|
715
|
+
}
|
|
716
|
+
}
|
|
712
717
|
// query for provenanceDb
|
|
713
718
|
const provenanceAspectsQuery = `
|
|
714
719
|
SELECT esa.Identifier, Element.Id
|
|
@@ -719,23 +724,22 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
719
724
|
// Technically this will a second time call the function (as documented) on
|
|
720
725
|
// victims of the old provenance method that have both fedguids and an inserted aspect.
|
|
721
726
|
// But this is a private function with one known caller where that doesn't matter
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
return IModelTransformer.forEachTrackedElement({
|
|
727
|
+
const runFnInDataFlowDirection = (sourceId, targetId) => args.isReverseSynchronization
|
|
728
|
+
? args.fn(sourceId, targetId)
|
|
729
|
+
: args.fn(targetId, sourceId);
|
|
730
|
+
const params = new core_common_1.QueryBinder();
|
|
731
|
+
params.bindId("scopeId", args.targetScopeElementId);
|
|
732
|
+
params.bindString("kind", core_backend_1.ExternalSourceAspect.Kind.Element);
|
|
733
|
+
const provenanceReader = args.provenanceDb.createQueryReader(provenanceAspectsQuery, params);
|
|
734
|
+
for await (const row of provenanceReader) {
|
|
735
|
+
// ExternalSourceAspect.Identifier is of type string
|
|
736
|
+
const aspectIdentifier = row[0];
|
|
737
|
+
const elementId = row.id;
|
|
738
|
+
runFnInDataFlowDirection(elementId, aspectIdentifier);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
async forEachTrackedElement(fn) {
|
|
742
|
+
return await IModelTransformer.forEachTrackedElement({
|
|
739
743
|
provenanceSourceDb: this.provenanceSourceDb,
|
|
740
744
|
provenanceDb: this.provenanceDb,
|
|
741
745
|
targetScopeElementId: this.targetScopeElementId,
|
|
@@ -751,23 +755,25 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
751
755
|
* @param entityInProvenanceSourceId
|
|
752
756
|
* @returns the elementId that the ESA is stored on, esa.Element.Id
|
|
753
757
|
*/
|
|
754
|
-
_queryProvenanceForElement(entityInProvenanceSourceId) {
|
|
758
|
+
async _queryProvenanceForElement(entityInProvenanceSourceId) {
|
|
755
759
|
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
756
|
-
|
|
760
|
+
const sql = `
|
|
757
761
|
SELECT esa.Element.Id
|
|
758
762
|
FROM Bis.ExternalSourceAspect esa
|
|
759
763
|
WHERE esa.Kind=?
|
|
760
764
|
AND esa.Scope.Id=?
|
|
761
765
|
AND esa.Identifier=?
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
}
|
|
766
|
+
`;
|
|
767
|
+
const params = new core_common_1.QueryBinder();
|
|
768
|
+
params.bindString(1, core_backend_1.ExternalSourceAspect.Kind.Element);
|
|
769
|
+
params.bindId(2, this.targetScopeElementId);
|
|
770
|
+
params.bindString(3, entityInProvenanceSourceId);
|
|
771
|
+
const result = this.provenanceDb.createQueryReader(sql, params);
|
|
772
|
+
if (await result.step()) {
|
|
773
|
+
return result.current.id;
|
|
774
|
+
}
|
|
775
|
+
else
|
|
776
|
+
return undefined;
|
|
771
777
|
}
|
|
772
778
|
/**
|
|
773
779
|
* Queries the provenanceDb for an ESA whose identifier is equal to the provided 'entityInProvenanceSourceId'.
|
|
@@ -776,35 +782,36 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
776
782
|
* @param entityInProvenanceSourceId
|
|
777
783
|
* @returns
|
|
778
784
|
*/
|
|
779
|
-
_queryProvenanceForRelationship(entityInProvenanceSourceId, sourceRelInfo) {
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
const
|
|
797
|
-
const
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
: this._queryTargetRelId(sourceRelInfo);
|
|
785
|
+
async _queryProvenanceForRelationship(entityInProvenanceSourceId, sourceRelInfo) {
|
|
786
|
+
const sql = `
|
|
787
|
+
SELECT
|
|
788
|
+
ECInstanceId,
|
|
789
|
+
JSON_EXTRACT(JsonProperties, '$.provenanceRelInstanceId') AS provenanceRelInstId
|
|
790
|
+
FROM Bis.ExternalSourceAspect
|
|
791
|
+
WHERE Kind=?
|
|
792
|
+
AND Scope.Id=?
|
|
793
|
+
AND Identifier=?
|
|
794
|
+
`;
|
|
795
|
+
const params = new core_common_1.QueryBinder();
|
|
796
|
+
params.bindString(1, core_backend_1.ExternalSourceAspect.Kind.Relationship);
|
|
797
|
+
params.bindId(2, this.targetScopeElementId);
|
|
798
|
+
params.bindString(3, entityInProvenanceSourceId);
|
|
799
|
+
const result = this.provenanceDb.createQueryReader(sql, params);
|
|
800
|
+
if (await result.step()) {
|
|
801
|
+
const aspectId = result.current.id;
|
|
802
|
+
const provenanceRelInstId = result.current.provenanceRelInstId;
|
|
803
|
+
const provenanceRelInstanceId = provenanceRelInstId !== undefined
|
|
804
|
+
? provenanceRelInstId
|
|
805
|
+
: await this._queryTargetRelId(sourceRelInfo);
|
|
801
806
|
return {
|
|
802
807
|
aspectId,
|
|
803
808
|
relationshipId: provenanceRelInstanceId,
|
|
804
809
|
};
|
|
805
|
-
}
|
|
810
|
+
}
|
|
811
|
+
else
|
|
812
|
+
return undefined;
|
|
806
813
|
}
|
|
807
|
-
_queryTargetRelId(sourceRelInfo) {
|
|
814
|
+
async _queryTargetRelId(sourceRelInfo) {
|
|
808
815
|
const targetRelInfo = {
|
|
809
816
|
sourceId: this.context.findTargetElementId(sourceRelInfo.sourceId),
|
|
810
817
|
targetId: this.context.findTargetElementId(sourceRelInfo.targetId),
|
|
@@ -812,60 +819,61 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
812
819
|
if (targetRelInfo.sourceId === undefined ||
|
|
813
820
|
targetRelInfo.targetId === undefined)
|
|
814
821
|
return undefined; // couldn't find an element, rel is invalid or deleted
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
return
|
|
829
|
-
|
|
822
|
+
const sql = `
|
|
823
|
+
select ecinstanceid
|
|
824
|
+
from bis.elementreferstoelements
|
|
825
|
+
where sourceecinstanceid=?
|
|
826
|
+
and targetecinstanceid=?
|
|
827
|
+
and ecclassid=?
|
|
828
|
+
`;
|
|
829
|
+
const params = new core_common_1.QueryBinder();
|
|
830
|
+
params.bindId(1, targetRelInfo.sourceId);
|
|
831
|
+
params.bindId(2, targetRelInfo.targetId);
|
|
832
|
+
params.bindId(3, await this._targetClassNameToClassId(sourceRelInfo.classFullName));
|
|
833
|
+
const result = this.targetDb.createQueryReader(sql, params);
|
|
834
|
+
if (await result.step())
|
|
835
|
+
return result.current.id;
|
|
836
|
+
else
|
|
837
|
+
return undefined;
|
|
830
838
|
}
|
|
831
839
|
_targetClassNameToClassIdCache = new Map();
|
|
832
|
-
_targetClassNameToClassId(classFullName) {
|
|
840
|
+
async _targetClassNameToClassId(classFullName) {
|
|
833
841
|
let classId = this._targetClassNameToClassIdCache.get(classFullName);
|
|
834
842
|
if (classId === undefined) {
|
|
835
|
-
classId = this._getRelClassId(this.targetDb, classFullName);
|
|
843
|
+
classId = await this._getRelClassId(this.targetDb, classFullName);
|
|
836
844
|
this._targetClassNameToClassIdCache.set(classFullName, classId);
|
|
837
845
|
}
|
|
838
846
|
return classId;
|
|
839
847
|
}
|
|
840
848
|
// NOTE: this doesn't handle remapped element classes,
|
|
841
849
|
// but is only used for relationships rn
|
|
842
|
-
_getRelClassId(db, classFullName) {
|
|
843
|
-
|
|
844
|
-
return db.withPreparedStatement(`
|
|
850
|
+
async _getRelClassId(db, classFullName) {
|
|
851
|
+
const sql = `
|
|
845
852
|
SELECT c.ECInstanceId
|
|
846
853
|
FROM ECDbMeta.ECClassDef c
|
|
847
854
|
JOIN ECDbMeta.ECSchemaDef s ON c.Schema.Id=s.ECInstanceId
|
|
848
855
|
WHERE s.Name=? AND c.Name=?
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
}
|
|
856
|
+
`;
|
|
857
|
+
const params = new core_common_1.QueryBinder();
|
|
858
|
+
const [schemaName, className] = classFullName.indexOf(".") !== -1
|
|
859
|
+
? classFullName.split(".")
|
|
860
|
+
: classFullName.split(":");
|
|
861
|
+
params.bindString(1, schemaName);
|
|
862
|
+
params.bindString(2, className);
|
|
863
|
+
const result = db.createQueryReader(sql, params);
|
|
864
|
+
if (await result.step())
|
|
865
|
+
return result.current.id;
|
|
866
|
+
(0, core_bentley_1.assert)(false, "relationship was not found");
|
|
867
|
+
}
|
|
868
|
+
// Deprecate?
|
|
869
|
+
async _queryElemIdByFedGuid(db, fedGuid) {
|
|
870
|
+
const sql = "SELECT ECInstanceId FROM Bis.Element WHERE FederationGuid=:fedGuid";
|
|
871
|
+
const params = new core_common_1.QueryBinder().bindString("fedGuid", fedGuid);
|
|
872
|
+
const reader = db.createQueryReader(sql, params);
|
|
873
|
+
if (await reader.step()) {
|
|
874
|
+
return reader.current.ecinstanceid;
|
|
875
|
+
}
|
|
876
|
+
return undefined;
|
|
869
877
|
}
|
|
870
878
|
/** Returns `true` if *brute force* delete detections should be run.
|
|
871
879
|
* @note This is only called if [[IModelTransformOptions.forceExternalSourceAspectProvenance]] option is true
|
|
@@ -919,7 +927,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
919
927
|
* @note A subclass can override this method to provide custom transform behavior.
|
|
920
928
|
* @note This can be called more than once for an element in arbitrary order, so it should not have side-effects.
|
|
921
929
|
*/
|
|
922
|
-
onTransformElement(sourceElement) {
|
|
930
|
+
async onTransformElement(sourceElement) {
|
|
923
931
|
core_bentley_1.Logger.logTrace(loggerCategory, `onTransformElement(${sourceElement.id}) "${sourceElement.getDisplayLabel()}"`);
|
|
924
932
|
const targetElementProps = this.context.cloneElement(sourceElement, { binaryGeometry: this._options.cloneUsingBinaryGeometry });
|
|
925
933
|
// Special case: source element is the root subject
|
|
@@ -1035,7 +1043,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1035
1043
|
sourceDbChanges.element.insertIds.has(sourceElement.id) ||
|
|
1036
1044
|
sourceDbChanges.element.updateIds.has(sourceElement.id));
|
|
1037
1045
|
}
|
|
1038
|
-
completePartiallyCommittedElements() {
|
|
1046
|
+
async completePartiallyCommittedElements() {
|
|
1039
1047
|
for (const sourceElementId of this._partiallyCommittedElementIds) {
|
|
1040
1048
|
const sourceElement = this.sourceDb.elements.getElement({
|
|
1041
1049
|
id: sourceElementId,
|
|
@@ -1046,25 +1054,25 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1046
1054
|
if (core_bentley_1.Id64.isInvalid(targetId)) {
|
|
1047
1055
|
throw new Error(`source-target element mapping not found for element "${sourceElementId}" when completing partially committed elements. This is a bug.`);
|
|
1048
1056
|
}
|
|
1049
|
-
const targetProps = this.onTransformElement(sourceElement);
|
|
1057
|
+
const targetProps = await this.onTransformElement(sourceElement);
|
|
1050
1058
|
this.targetDb.elements.updateElement({ ...targetProps, id: targetId });
|
|
1051
1059
|
}
|
|
1052
1060
|
}
|
|
1053
|
-
completePartiallyCommittedAspects() {
|
|
1061
|
+
async completePartiallyCommittedAspects() {
|
|
1054
1062
|
for (const sourceAspectId of this._partiallyCommittedAspectIds) {
|
|
1055
1063
|
const sourceAspect = this.sourceDb.elements.getAspect(sourceAspectId);
|
|
1056
1064
|
const targetAspectId = this.context.findTargetAspectId(sourceAspectId);
|
|
1057
1065
|
if (core_bentley_1.Id64.isInvalid(targetAspectId)) {
|
|
1058
1066
|
throw new Error(`source-target aspect mapping not found for aspect "${sourceAspectId}" when completing partially committed aspects. This is a bug.`);
|
|
1059
1067
|
}
|
|
1060
|
-
const targetAspectProps = this.onTransformElementAspect(sourceAspect);
|
|
1068
|
+
const targetAspectProps = await this.onTransformElementAspect(sourceAspect);
|
|
1061
1069
|
this.targetDb.elements.updateAspect({
|
|
1062
1070
|
...targetAspectProps,
|
|
1063
1071
|
id: targetAspectId,
|
|
1064
1072
|
});
|
|
1065
1073
|
}
|
|
1066
1074
|
}
|
|
1067
|
-
doAllReferencesExistInTarget(entity) {
|
|
1075
|
+
async doAllReferencesExistInTarget(entity) {
|
|
1068
1076
|
let allReferencesExist = true;
|
|
1069
1077
|
for (const referenceId of entity.getReferenceIds()) {
|
|
1070
1078
|
const referencedEntityId = core_backend_1.EntityReferences.toId64(referenceId);
|
|
@@ -1074,7 +1082,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1074
1082
|
continue;
|
|
1075
1083
|
}
|
|
1076
1084
|
if (allReferencesExist &&
|
|
1077
|
-
!core_backend_1.EntityReferences.isValid(this.context.findTargetEntityId(referenceId))) {
|
|
1085
|
+
!core_backend_1.EntityReferences.isValid(await this.context.findTargetEntityId(referenceId))) {
|
|
1078
1086
|
// if we care about references existing then we cannot return early and must check all other references.
|
|
1079
1087
|
if (this._options.danglingReferencesBehavior === "ignore") {
|
|
1080
1088
|
return false;
|
|
@@ -1130,6 +1138,10 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1130
1138
|
* @internal do not call, override or implement this, it will be removed
|
|
1131
1139
|
*/
|
|
1132
1140
|
async preExportElement(sourceElement) {
|
|
1141
|
+
if (!this.hasElementChanged(sourceElement)) {
|
|
1142
|
+
core_bentley_1.Logger.logTrace(loggerCategory, `Skipping unchanged element (${sourceElement.id}, ${sourceElement.getDisplayLabel()}).`);
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1133
1145
|
const elemClass = sourceElement.constructor;
|
|
1134
1146
|
const unresolvedReferences = elemClass.requiredReferenceKeys
|
|
1135
1147
|
.map((referenceKey) => {
|
|
@@ -1188,8 +1200,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1188
1200
|
/** Override of [IModelExportHandler.onExportElement]($transformer) that imports an element into the target iModel when it is exported from the source iModel.
|
|
1189
1201
|
* This override calls [[onTransformElement]] and then [IModelImporter.importElement]($transformer) to update the target iModel.
|
|
1190
1202
|
*/
|
|
1191
|
-
onExportElement(sourceElement) {
|
|
1192
|
-
let targetElementId;
|
|
1203
|
+
async onExportElement(sourceElement) {
|
|
1204
|
+
let targetElementId = core_bentley_1.Id64.invalid;
|
|
1193
1205
|
let targetElementProps;
|
|
1194
1206
|
if (this._options.wasSourceIModelCopiedToTarget) {
|
|
1195
1207
|
targetElementId = sourceElement.id;
|
|
@@ -1198,14 +1210,14 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1198
1210
|
}
|
|
1199
1211
|
else {
|
|
1200
1212
|
targetElementId = this.context.findTargetElementId(sourceElement.id);
|
|
1201
|
-
targetElementProps = this.onTransformElement(sourceElement);
|
|
1213
|
+
targetElementProps = await this.onTransformElement(sourceElement);
|
|
1202
1214
|
}
|
|
1203
1215
|
// if an existing remapping was not yet found, check by FederationGuid
|
|
1204
1216
|
if (this.context.isBetweenIModels &&
|
|
1205
1217
|
!core_bentley_1.Id64.isValid(targetElementId) &&
|
|
1206
1218
|
sourceElement.federationGuid !== undefined) {
|
|
1207
1219
|
targetElementId =
|
|
1208
|
-
this.
|
|
1220
|
+
this.targetDb.elements.getIdFromFederationGuid(sourceElement.federationGuid) ?? core_bentley_1.Id64.invalid;
|
|
1209
1221
|
if (core_bentley_1.Id64.isValid(targetElementId))
|
|
1210
1222
|
this.context.remapElement(sourceElement.id, targetElementId); // record that the targetElement was found
|
|
1211
1223
|
}
|
|
@@ -1232,7 +1244,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1232
1244
|
core_bentley_1.Logger.logTrace(loggerCategory, `Skipping unchanged element (${sourceElement.id}, ${sourceElement.getDisplayLabel()}).`);
|
|
1233
1245
|
return;
|
|
1234
1246
|
}
|
|
1235
|
-
if (!this.doAllReferencesExistInTarget(sourceElement)) {
|
|
1247
|
+
if (!(await this.doAllReferencesExistInTarget(sourceElement))) {
|
|
1236
1248
|
this._partiallyCommittedElementIds.add(sourceElement.id);
|
|
1237
1249
|
}
|
|
1238
1250
|
// targetElementId will be valid (indicating update) or undefined (indicating insert)
|
|
@@ -1322,7 +1334,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1322
1334
|
this.importer.importModel(targetModelProps);
|
|
1323
1335
|
}
|
|
1324
1336
|
/** Override of [IModelExportHandler.onDeleteModel]($transformer) that is called when [IModelExporter]($transformer) detects that a [Model]($backend) has been deleted from the source iModel. */
|
|
1325
|
-
onDeleteModel(sourceModelId) {
|
|
1337
|
+
async onDeleteModel(sourceModelId) {
|
|
1326
1338
|
// It is possible and apparently occasionally sensical to delete a model without deleting its underlying element.
|
|
1327
1339
|
// - If only the model is deleted, [[initFromExternalSourceAspects]] will have already remapped the underlying element since it still exists.
|
|
1328
1340
|
// - If both were deleted, [[remapDeletedSourceEntities]] will find and remap the deleted element making this operation valid
|
|
@@ -1339,19 +1351,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1339
1351
|
WHERE ECInstanceId=:targetModelId
|
|
1340
1352
|
`;
|
|
1341
1353
|
if (this.exporter.sourceDbChanges?.element.deleteIds.has(sourceModelId)) {
|
|
1342
|
-
|
|
1343
|
-
const
|
|
1344
|
-
|
|
1345
|
-
const val = stmt.step();
|
|
1346
|
-
switch (val) {
|
|
1347
|
-
case core_bentley_1.DbResult.BE_SQLITE_ROW:
|
|
1348
|
-
return true;
|
|
1349
|
-
case core_bentley_1.DbResult.BE_SQLITE_DONE:
|
|
1350
|
-
return false;
|
|
1351
|
-
default:
|
|
1352
|
-
(0, core_bentley_1.assert)(false, `unexpected db result: '${JSON.stringify(stmt)}'`);
|
|
1353
|
-
}
|
|
1354
|
-
});
|
|
1354
|
+
const params = new core_common_1.QueryBinder().bindId("targetModelId", targetModelId);
|
|
1355
|
+
const reader = this.targetDb.createQueryReader(sql, params);
|
|
1356
|
+
const isDefinitionPartition = await reader.step();
|
|
1355
1357
|
if (isDefinitionPartition) {
|
|
1356
1358
|
// Skipping model deletion because model's partition will also be deleted.
|
|
1357
1359
|
// It expects that model will be present and will fail if it's missing.
|
|
@@ -1360,7 +1362,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1360
1362
|
}
|
|
1361
1363
|
}
|
|
1362
1364
|
try {
|
|
1363
|
-
this.importer.deleteModel(targetModelId);
|
|
1365
|
+
await this.importer.deleteModel(targetModelId);
|
|
1364
1366
|
}
|
|
1365
1367
|
catch (error) {
|
|
1366
1368
|
const isDeletionProhibitedErr = error instanceof core_common_1.IModelError &&
|
|
@@ -1407,41 +1409,24 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1407
1409
|
await this.initialize();
|
|
1408
1410
|
// import DefinitionModels first
|
|
1409
1411
|
const childDefinitionPartitionSql = `SELECT ECInstanceId FROM ${core_backend_1.DefinitionPartition.classFullName} WHERE Parent.Id=:subjectId`;
|
|
1410
|
-
|
|
1411
|
-
await this.sourceDb.
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
statement.bindId("subjectId", sourceSubjectId);
|
|
1415
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
|
|
1416
|
-
await this.processModel(statement.getValue(0).getId());
|
|
1417
|
-
}
|
|
1418
|
-
});
|
|
1412
|
+
const params = new core_common_1.QueryBinder().bindId("subjectId", sourceSubjectId);
|
|
1413
|
+
for await (const row of this.sourceDb.createQueryReader(childDefinitionPartitionSql, params)) {
|
|
1414
|
+
await this.processModel(row.id);
|
|
1415
|
+
}
|
|
1419
1416
|
// import other partitions next
|
|
1420
1417
|
const childPartitionSql = `SELECT ECInstanceId FROM ${core_backend_1.InformationPartitionElement.classFullName} WHERE Parent.Id=:subjectId`;
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
|
|
1427
|
-
const modelId = statement.getValue(0).getId();
|
|
1428
|
-
const model = this.sourceDb.models.getModel(modelId);
|
|
1429
|
-
if (!(model instanceof core_backend_1.DefinitionModel)) {
|
|
1430
|
-
await this.processModel(modelId);
|
|
1431
|
-
}
|
|
1418
|
+
for await (const row of this.sourceDb.createQueryReader(childPartitionSql, params)) {
|
|
1419
|
+
const modelId = row.id;
|
|
1420
|
+
const model = this.sourceDb.models.getModel(modelId);
|
|
1421
|
+
if (!(model instanceof core_backend_1.DefinitionModel)) {
|
|
1422
|
+
await this.processModel(modelId);
|
|
1432
1423
|
}
|
|
1433
|
-
}
|
|
1424
|
+
}
|
|
1434
1425
|
// recurse into child Subjects
|
|
1435
1426
|
const childSubjectSql = `SELECT ECInstanceId FROM ${core_backend_1.Subject.classFullName} WHERE Parent.Id=:subjectId`;
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
async (statement) => {
|
|
1440
|
-
statement.bindId("subjectId", sourceSubjectId);
|
|
1441
|
-
while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
|
|
1442
|
-
await this.processSubjectSubModels(statement.getValue(0).getId());
|
|
1443
|
-
}
|
|
1444
|
-
});
|
|
1427
|
+
for await (const row of this.sourceDb.createQueryReader(childSubjectSql, params)) {
|
|
1428
|
+
await this.processSubjectSubModels(row.id);
|
|
1429
|
+
}
|
|
1445
1430
|
}
|
|
1446
1431
|
/** Transform the specified sourceModel into ModelProps for the target iModel.
|
|
1447
1432
|
* @param sourceModel The Model from the source iModel to be transformed.
|
|
@@ -1588,9 +1573,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1588
1573
|
/** Override of [IModelExportHandler.onExportRelationship]($transformer) that imports a relationship into the target iModel when it is exported from the source iModel.
|
|
1589
1574
|
* This override calls [[onTransformRelationship]] and then [IModelImporter.importRelationship]($transformer) to update the target iModel.
|
|
1590
1575
|
*/
|
|
1591
|
-
onExportRelationship(sourceRelationship) {
|
|
1592
|
-
const sourceFedGuid =
|
|
1593
|
-
const targetFedGuid =
|
|
1576
|
+
async onExportRelationship(sourceRelationship) {
|
|
1577
|
+
const sourceFedGuid = this.sourceDb.elements.getFederationGuidFromId(sourceRelationship.sourceId);
|
|
1578
|
+
const targetFedGuid = this.sourceDb.elements.getFederationGuidFromId(sourceRelationship.targetId);
|
|
1594
1579
|
const targetRelationshipProps = this.onTransformRelationship(sourceRelationship);
|
|
1595
1580
|
const targetRelationshipInstanceId = this.importer.importRelationship(targetRelationshipProps);
|
|
1596
1581
|
if (!this._options.noProvenance &&
|
|
@@ -1599,7 +1584,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1599
1584
|
? sourceFedGuid && targetFedGuid && `${sourceFedGuid}/${targetFedGuid}`
|
|
1600
1585
|
: undefined;
|
|
1601
1586
|
if (!provenance) {
|
|
1602
|
-
const aspectProps = this.initRelationshipProvenance(sourceRelationship, targetRelationshipInstanceId);
|
|
1587
|
+
const aspectProps = await this.initRelationshipProvenance(sourceRelationship, targetRelationshipInstanceId);
|
|
1603
1588
|
const foundEsaProps = IModelTransformer.queryScopeExternalSourceAspect(this.provenanceDb, aspectProps);
|
|
1604
1589
|
// onExportRelationship doesn't need to call updateAspect if esaProps were found, because relationship provenance doesn't have the same concept of a version as element provenance (which uses last mod time on the elements).
|
|
1605
1590
|
if (undefined === foundEsaProps) {
|
|
@@ -1662,32 +1647,27 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1662
1647
|
WHERE aspect.Scope.Id=:scopeId
|
|
1663
1648
|
AND aspect.Kind=:kind
|
|
1664
1649
|
`;
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
this.importer.deleteRelationship({
|
|
1682
|
-
id: targetRelInstanceId,
|
|
1683
|
-
classFullName: core_backend_1.ElementRefersToElements.classFullName,
|
|
1684
|
-
});
|
|
1685
|
-
}
|
|
1686
|
-
aspectDeleteIds.push(statement.getValue(0).getId());
|
|
1650
|
+
const params = new core_common_1.QueryBinder().bindId("scopeId", this.targetScopeElementId);
|
|
1651
|
+
params.bindString("kind", core_backend_1.ExternalSourceAspect.Kind.Relationship);
|
|
1652
|
+
for await (const row of this.targetDb.createQueryReader(sql, params)) {
|
|
1653
|
+
const sourceRelInstanceId = core_bentley_1.Id64.fromJSON(row[1]);
|
|
1654
|
+
if (undefined ===
|
|
1655
|
+
this.sourceDb.relationships.tryGetInstanceProps(core_backend_1.ElementRefersToElements.classFullName, sourceRelInstanceId)) {
|
|
1656
|
+
// this function exists only to support some in-imodel transformations, which must
|
|
1657
|
+
// use the old (external source aspect) provenance method anyway so we don't need to support
|
|
1658
|
+
// new provenance
|
|
1659
|
+
const json = JSON.parse(row[2]);
|
|
1660
|
+
const targetRelInstanceId = json.targetRelInstanceId ?? json.provenanceRelInstanceId;
|
|
1661
|
+
if (targetRelInstanceId) {
|
|
1662
|
+
this.importer.deleteRelationship({
|
|
1663
|
+
id: targetRelInstanceId,
|
|
1664
|
+
classFullName: core_backend_1.ElementRefersToElements.classFullName,
|
|
1665
|
+
});
|
|
1687
1666
|
}
|
|
1688
|
-
|
|
1667
|
+
aspectDeleteIds.push(row.id);
|
|
1689
1668
|
}
|
|
1690
|
-
|
|
1669
|
+
await this._yieldManager.allowYield();
|
|
1670
|
+
}
|
|
1691
1671
|
this.targetDb.elements.deleteAspect(aspectDeleteIds);
|
|
1692
1672
|
}
|
|
1693
1673
|
/** Transform the specified sourceRelationship into RelationshipProps for the target iModel.
|
|
@@ -1700,11 +1680,10 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1700
1680
|
targetRelationshipProps.sourceId = this.context.findTargetElementId(sourceRelationship.sourceId);
|
|
1701
1681
|
targetRelationshipProps.targetId = this.context.findTargetElementId(sourceRelationship.targetId);
|
|
1702
1682
|
// TODO: move to cloneRelationship in IModelCloneContext
|
|
1703
|
-
sourceRelationship.
|
|
1704
|
-
if (
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
this.context.findTargetElementId(sourceRelationship.asAny[propertyName]);
|
|
1683
|
+
sourceRelationship.forEach((propertyName, property) => {
|
|
1684
|
+
if (property.isPrimitive() && "Id" === property.extendedTypeName) {
|
|
1685
|
+
targetRelationshipProps[core_common_1.ECJsNames.toJsName(propertyName)] =
|
|
1686
|
+
this.context.findTargetElementId(sourceRelationship.asAny[core_common_1.ECJsNames.toJsName(propertyName)]);
|
|
1708
1687
|
}
|
|
1709
1688
|
});
|
|
1710
1689
|
return targetRelationshipProps;
|
|
@@ -1717,9 +1696,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1717
1696
|
/** Override of [IModelExportHandler.onExportElementUniqueAspect]($transformer) that imports an ElementUniqueAspect into the target iModel when it is exported from the source iModel.
|
|
1718
1697
|
* This override calls [[onTransformElementAspect]] and then [IModelImporter.importElementUniqueAspect]($transformer) to update the target iModel.
|
|
1719
1698
|
*/
|
|
1720
|
-
onExportElementUniqueAspect(sourceAspect) {
|
|
1721
|
-
const targetAspectProps = this.onTransformElementAspect(sourceAspect);
|
|
1722
|
-
if (!this.doAllReferencesExistInTarget(sourceAspect)) {
|
|
1699
|
+
async onExportElementUniqueAspect(sourceAspect) {
|
|
1700
|
+
const targetAspectProps = await this.onTransformElementAspect(sourceAspect);
|
|
1701
|
+
if (!(await this.doAllReferencesExistInTarget(sourceAspect))) {
|
|
1723
1702
|
this._partiallyCommittedAspectIds.add(sourceAspect.id);
|
|
1724
1703
|
}
|
|
1725
1704
|
const targetId = this.importer.importElementUniqueAspect(targetAspectProps);
|
|
@@ -1729,16 +1708,16 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1729
1708
|
* This override calls [[onTransformElementAspect]] for each ElementMultiAspect and then [IModelImporter.importElementMultiAspects]($transformer) to update the target iModel.
|
|
1730
1709
|
* @note ElementMultiAspects are handled as a group to make it easier to differentiate between insert, update, and delete.
|
|
1731
1710
|
*/
|
|
1732
|
-
onExportElementMultiAspects(sourceAspects) {
|
|
1711
|
+
async onExportElementMultiAspects(sourceAspects) {
|
|
1733
1712
|
// Transform source ElementMultiAspects into target ElementAspectProps
|
|
1734
|
-
const targetAspectPropsArray = sourceAspects.map((srcA) => this.onTransformElementAspect(srcA));
|
|
1735
|
-
sourceAspects.forEach((a) => {
|
|
1736
|
-
if (!this.doAllReferencesExistInTarget(a)) {
|
|
1713
|
+
const targetAspectPropsArray = sourceAspects.map(async (srcA) => await this.onTransformElementAspect(srcA));
|
|
1714
|
+
sourceAspects.forEach(async (a) => {
|
|
1715
|
+
if (!(await this.doAllReferencesExistInTarget(a))) {
|
|
1737
1716
|
this._partiallyCommittedAspectIds.add(a.id);
|
|
1738
1717
|
}
|
|
1739
1718
|
});
|
|
1740
1719
|
// const targetAspectsToImport = targetAspectPropsArray.filter((targetAspect, i) => hasEntityChanged(sourceAspects[i], targetAspect));
|
|
1741
|
-
const targetIds = this.importer.importElementMultiAspects(targetAspectPropsArray, (a) => {
|
|
1720
|
+
const targetIds = this.importer.importElementMultiAspects(await Promise.all(targetAspectPropsArray), (a) => {
|
|
1742
1721
|
const isExternalSourceAspectFromTransformer = a instanceof core_backend_1.ExternalSourceAspect &&
|
|
1743
1722
|
a.scope?.id === this.targetScopeElementId;
|
|
1744
1723
|
return (!this._options.includeSourceProvenance ||
|
|
@@ -1753,8 +1732,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1753
1732
|
* @returns ElementAspectProps for the target iModel.
|
|
1754
1733
|
* @note A subclass can override this method to provide custom transform behavior.
|
|
1755
1734
|
*/
|
|
1756
|
-
onTransformElementAspect(sourceElementAspect) {
|
|
1757
|
-
const targetElementAspectProps = this.context.cloneElementAspect(sourceElementAspect);
|
|
1735
|
+
async onTransformElementAspect(sourceElementAspect) {
|
|
1736
|
+
const targetElementAspectProps = await this.context.cloneElementAspect(sourceElementAspect);
|
|
1758
1737
|
return targetElementAspectProps;
|
|
1759
1738
|
}
|
|
1760
1739
|
/** The directory where schemas will be exported, a random temporary directory */
|
|
@@ -1796,7 +1775,6 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1796
1775
|
nodeAssert(schemaFileName.length <= systemMaxPathSegmentSize, "Schema name was still long. This is a bug.");
|
|
1797
1776
|
this._longNamedSchemasMap.set(schema.name, schemaFileName);
|
|
1798
1777
|
}
|
|
1799
|
-
/* eslint-disable-next-line @typescript-eslint/no-deprecated */
|
|
1800
1778
|
this.sourceDb.exportSchema({
|
|
1801
1779
|
schemaName: schema.name,
|
|
1802
1780
|
outputDirectory: this._schemaExportDir,
|
|
@@ -1884,8 +1862,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1884
1862
|
this.context.remapElement(sourceSubjectId, targetSubjectId);
|
|
1885
1863
|
await this.processChildElements(sourceSubjectId);
|
|
1886
1864
|
await this.processSubjectSubModels(sourceSubjectId);
|
|
1887
|
-
this.completePartiallyCommittedElements();
|
|
1888
|
-
this.completePartiallyCommittedAspects();
|
|
1865
|
+
await this.completePartiallyCommittedElements();
|
|
1866
|
+
await this.completePartiallyCommittedAspects();
|
|
1889
1867
|
}
|
|
1890
1868
|
/** state to prevent reinitialization, @see [[initialize]] */
|
|
1891
1869
|
_initialized = false;
|
|
@@ -1901,7 +1879,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1901
1879
|
async initialize() {
|
|
1902
1880
|
if (this._initialized)
|
|
1903
1881
|
return;
|
|
1904
|
-
this.initScopeProvenance();
|
|
1882
|
+
await this.initScopeProvenance();
|
|
1905
1883
|
await this._tryInitChangesetData(this._options.argsForProcessChanges);
|
|
1906
1884
|
await this.context.initialize();
|
|
1907
1885
|
// need exporter initialized to do remapdeletedsourceentities.
|
|
@@ -1917,7 +1895,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1917
1895
|
* @returns void
|
|
1918
1896
|
*/
|
|
1919
1897
|
async processChangesets() {
|
|
1920
|
-
this.forEachTrackedElement((sourceElementId, targetElementId) => {
|
|
1898
|
+
await this.forEachTrackedElement((sourceElementId, targetElementId) => {
|
|
1921
1899
|
this.context.remapElement(sourceElementId, targetElementId);
|
|
1922
1900
|
});
|
|
1923
1901
|
if (this.exporter.sourceDbChanges)
|
|
@@ -2055,7 +2033,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2055
2033
|
}
|
|
2056
2034
|
// Check for targetId using sourceId's fedguid if we didn't find an esa.
|
|
2057
2035
|
if (fedGuid) {
|
|
2058
|
-
const targetId = this.
|
|
2036
|
+
const targetId = this.targetDb.elements.getIdFromFederationGuid(fedGuid);
|
|
2059
2037
|
return targetId;
|
|
2060
2038
|
}
|
|
2061
2039
|
return undefined;
|
|
@@ -2075,7 +2053,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2075
2053
|
});
|
|
2076
2054
|
}
|
|
2077
2055
|
else if (this.sourceDb === this.provenanceSourceDb) {
|
|
2078
|
-
const relProvenance = this._queryProvenanceForRelationship(changedInstanceId, {
|
|
2056
|
+
const relProvenance = await this._queryProvenanceForRelationship(changedInstanceId, {
|
|
2079
2057
|
classFullName: classFullName ?? "",
|
|
2080
2058
|
sourceId: sourceIdOfRelationshipInSource,
|
|
2081
2059
|
targetId: targetIdOfRelationshipInSource,
|
|
@@ -2091,7 +2069,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2091
2069
|
else {
|
|
2092
2070
|
let targetId = await getTargetIdFromSourceId(changedInstanceId);
|
|
2093
2071
|
if (targetId === undefined && this.sourceDb === this.provenanceSourceDb) {
|
|
2094
|
-
targetId = this._queryProvenanceForElement(changedInstanceId);
|
|
2072
|
+
targetId = await this._queryProvenanceForElement(changedInstanceId);
|
|
2095
2073
|
}
|
|
2096
2074
|
// since we are processing one changeset at a time, we can see local source deletes
|
|
2097
2075
|
// of entities that were never synced and can be safely ignored
|
|
@@ -2136,7 +2114,6 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2136
2114
|
? indexOrId
|
|
2137
2115
|
: core_backend_1.BriefcaseManager.queryChangeset({
|
|
2138
2116
|
iModelId: this.sourceDb.iModelId,
|
|
2139
|
-
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
2140
2117
|
changeset: { id: indexOrId },
|
|
2141
2118
|
}).then((changeset) => changeset.index)));
|
|
2142
2119
|
const missingChangesets = startChangesetIndex > this.synchronizationVersion.index + 1;
|
|
@@ -2221,9 +2198,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2221
2198
|
else {
|
|
2222
2199
|
await this.exporter.exportModel(core_common_1.IModel.repositoryModelId);
|
|
2223
2200
|
}
|
|
2224
|
-
this.completePartiallyCommittedElements();
|
|
2201
|
+
await this.completePartiallyCommittedElements();
|
|
2225
2202
|
await this.exporter["exportAllAspects"](); // eslint-disable-line @typescript-eslint/dot-notation
|
|
2226
|
-
this.completePartiallyCommittedAspects();
|
|
2203
|
+
await this.completePartiallyCommittedAspects();
|
|
2227
2204
|
await this.exporter.exportRelationships(core_backend_1.ElementRefersToElements.classFullName);
|
|
2228
2205
|
if (this._options.forceExternalSourceAspectProvenance &&
|
|
2229
2206
|
this.shouldDetectDeletes()) {
|
|
@@ -2264,8 +2241,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2264
2241
|
async processChanges(options) {
|
|
2265
2242
|
// must wait for initialization of synchronization provenance data
|
|
2266
2243
|
await this.exporter.exportChanges(this.getExportInitOpts(options));
|
|
2267
|
-
this.completePartiallyCommittedElements();
|
|
2268
|
-
this.completePartiallyCommittedAspects();
|
|
2244
|
+
await this.completePartiallyCommittedElements();
|
|
2245
|
+
await this.completePartiallyCommittedAspects();
|
|
2269
2246
|
if (this._options.optimizeGeometry)
|
|
2270
2247
|
this.importer.optimizeGeometry(this._options.optimizeGeometry);
|
|
2271
2248
|
this.importer.computeProjectExtents();
|
|
@@ -2373,11 +2350,11 @@ class TemplateModelCloner extends IModelTransformer {
|
|
|
2373
2350
|
return this._sourceIdToTargetIdMap; // return the sourceElementId -> targetElementId Map in case further post-processing is required.
|
|
2374
2351
|
}
|
|
2375
2352
|
/** Cloning from a template requires this override of onTransformElement. */
|
|
2376
|
-
onTransformElement(sourceElement) {
|
|
2353
|
+
async onTransformElement(sourceElement) {
|
|
2377
2354
|
const referenceIds = sourceElement.getReferenceIds();
|
|
2378
|
-
|
|
2355
|
+
for (const referenceId of referenceIds) {
|
|
2379
2356
|
// TODO: consider going through all definition elements at once and remapping them to themselves
|
|
2380
|
-
if (!core_backend_1.EntityReferences.isValid(this.context.findTargetEntityId(referenceId))) {
|
|
2357
|
+
if (!core_backend_1.EntityReferences.isValid(await this.context.findTargetEntityId(referenceId))) {
|
|
2381
2358
|
if (this.context.isBetweenIModels) {
|
|
2382
2359
|
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, `Remapping for source dependency ${referenceId} not found for target iModel`);
|
|
2383
2360
|
}
|
|
@@ -2392,8 +2369,8 @@ class TemplateModelCloner extends IModelTransformer {
|
|
|
2392
2369
|
}
|
|
2393
2370
|
}
|
|
2394
2371
|
}
|
|
2395
|
-
}
|
|
2396
|
-
const targetElementProps = super.onTransformElement(sourceElement);
|
|
2372
|
+
}
|
|
2373
|
+
const targetElementProps = await super.onTransformElement(sourceElement);
|
|
2397
2374
|
targetElementProps.federationGuid = core_bentley_1.Guid.createValue(); // clone from template should create a new federationGuid
|
|
2398
2375
|
targetElementProps.code = core_common_1.Code.createEmpty(); // clone from template should not maintain codes
|
|
2399
2376
|
if (sourceElement instanceof core_backend_1.GeometricElement) {
|
|
@@ -2411,6 +2388,7 @@ class TemplateModelCloner extends IModelTransformer {
|
|
|
2411
2388
|
}
|
|
2412
2389
|
}
|
|
2413
2390
|
exports.TemplateModelCloner = TemplateModelCloner;
|
|
2391
|
+
//Deprecate in preference of imodeldb.elements.getFederationGuidFromId()?
|
|
2414
2392
|
function queryElemFedGuid(db, elemId) {
|
|
2415
2393
|
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
2416
2394
|
return db.withPreparedStatement(`
|