@itwin/imodel-transformer 2.0.0-dev.2 → 2.0.0-dev.4
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 +9 -1
- package/lib/cjs/BranchProvenanceInitializer.js +4 -4
- package/lib/cjs/BranchProvenanceInitializer.js.map +1 -1
- package/lib/cjs/ECReferenceTypesCache.d.ts +3 -0
- package/lib/cjs/ECReferenceTypesCache.d.ts.map +1 -1
- package/lib/cjs/ECReferenceTypesCache.js +102 -38
- package/lib/cjs/ECReferenceTypesCache.js.map +1 -1
- package/lib/cjs/ElementCascadingDeleter.js +1 -1
- package/lib/cjs/ElementCascadingDeleter.js.map +1 -1
- package/lib/cjs/EntityUnifier.d.ts.map +1 -1
- package/lib/cjs/EntityUnifier.js +3 -2
- package/lib/cjs/EntityUnifier.js.map +1 -1
- package/lib/cjs/IModelCloneContext.js +2 -2
- package/lib/cjs/IModelCloneContext.js.map +1 -1
- package/lib/cjs/IModelExporter.d.ts.map +1 -1
- package/lib/cjs/IModelExporter.js +10 -12
- package/lib/cjs/IModelExporter.js.map +1 -1
- package/lib/cjs/IModelImporter.d.ts.map +1 -1
- package/lib/cjs/IModelImporter.js +10 -6
- package/lib/cjs/IModelImporter.js.map +1 -1
- package/lib/cjs/IModelTransformer.d.ts +28 -1
- package/lib/cjs/IModelTransformer.d.ts.map +1 -1
- package/lib/cjs/IModelTransformer.js +152 -40
- package/lib/cjs/IModelTransformer.js.map +1 -1
- package/lib/cjs/TransformerLoggerCategory.d.ts +6 -5
- package/lib/cjs/TransformerLoggerCategory.d.ts.map +1 -1
- package/lib/cjs/TransformerLoggerCategory.js +6 -5
- package/lib/cjs/TransformerLoggerCategory.js.map +1 -1
- package/lib/cjs/imodel-transformer.js +2 -2
- package/lib/cjs/imodel-transformer.js.map +1 -1
- package/package.json +32 -32
|
@@ -77,6 +77,15 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
77
77
|
targetDb;
|
|
78
78
|
/** The IModelTransformContext for this IModelTransformer. */
|
|
79
79
|
context;
|
|
80
|
+
/** The transform to be applied to the placement of spatial elements
|
|
81
|
+
* This transform should be applied when:
|
|
82
|
+
* - source and target db have different ECEF locations
|
|
83
|
+
* - source and target db have matching GCS/CRS data, but differing `geographicCoordinateSystem.additionalTransform.helmert2DWithZOffset`
|
|
84
|
+
* @note for ECEF transforms, this can only be used when source and target are linearly located imodels
|
|
85
|
+
* @note for non linearly located imodels, this transform will be a linear transform derived from Helmert Transforms from the src and target iModels.
|
|
86
|
+
* @beta
|
|
87
|
+
*/
|
|
88
|
+
_linearSpatialTransform;
|
|
80
89
|
_syncType;
|
|
81
90
|
/** The Id of the Element in the **target** iModel that represents the **source** repository as a whole and scopes its [ExternalSourceAspect]($backend) instances. */
|
|
82
91
|
get targetScopeElementId() {
|
|
@@ -111,7 +120,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
111
120
|
AND Identifier=:identifier
|
|
112
121
|
LIMIT 1
|
|
113
122
|
`;
|
|
114
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
123
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
115
124
|
return dbToQuery.withPreparedStatement(sql, (statement) => {
|
|
116
125
|
statement.bindId("elementId", aspectProps.element.id);
|
|
117
126
|
if (aspectProps.scope === undefined)
|
|
@@ -230,10 +239,11 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
230
239
|
// non-falsy defaults
|
|
231
240
|
cloneUsingBinaryGeometry: options?.cloneUsingBinaryGeometry ?? true,
|
|
232
241
|
targetScopeElementId: options?.targetScopeElementId ?? core_common_1.IModel.rootSubjectId,
|
|
233
|
-
// eslint-disable-next-line
|
|
242
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
234
243
|
danglingReferencesBehavior: options?.danglingReferencesBehavior ?? "reject",
|
|
235
244
|
branchRelationshipDataBehavior: options?.branchRelationshipDataBehavior ?? "reject",
|
|
236
245
|
skipPropagateChangesToRootElements: options?.skipPropagateChangesToRootElements ?? true,
|
|
246
|
+
tryAlignGeolocation: options?.tryAlignGeolocation ?? false,
|
|
237
247
|
};
|
|
238
248
|
// check if authorization client is defined
|
|
239
249
|
if (core_backend_1.IModelHost.authorizationClient === undefined) {
|
|
@@ -289,6 +299,20 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
289
299
|
this.targetDb.codeValueBehavior = "exact";
|
|
290
300
|
}
|
|
291
301
|
/* eslint-enable @itwin/no-internal */
|
|
302
|
+
if (this._options.tryAlignGeolocation) {
|
|
303
|
+
if (this.sourceDb.geographicCoordinateSystem ||
|
|
304
|
+
this.targetDb.geographicCoordinateSystem) {
|
|
305
|
+
core_bentley_1.Logger.logTrace(loggerCategory, "Aligning Additional transforms between imodels due to imodels containing GeographicCoordinateSystem data");
|
|
306
|
+
this._linearSpatialTransform =
|
|
307
|
+
this.calculateTransformFromHelmertTransforms();
|
|
308
|
+
}
|
|
309
|
+
else if (this.sourceDb.ecefLocation && this.targetDb.ecefLocation) {
|
|
310
|
+
core_bentley_1.Logger.logTrace(loggerCategory, "Aligning ECEF Location's between imodels due to imodels not containing GeographicCoordinateSystem data");
|
|
311
|
+
this._linearSpatialTransform = this.calculateEcefTransform();
|
|
312
|
+
}
|
|
313
|
+
else
|
|
314
|
+
core_bentley_1.Logger.logTrace(loggerCategory, "No Geolcation data to align, both GCS and ECEF are undefined");
|
|
315
|
+
}
|
|
292
316
|
}
|
|
293
317
|
/** validates that the importer set on the transformer has the same values for its shared options as the transformer.
|
|
294
318
|
* @note This expects that the importer is already set on the transformer.
|
|
@@ -371,7 +395,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
371
395
|
const provenanceRelInstanceId = args.isReverseSynchronization
|
|
372
396
|
? sourceRelInstanceId
|
|
373
397
|
: targetRelInstanceId;
|
|
374
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
398
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
375
399
|
const elementId = provenanceDb.withPreparedStatement("SELECT SourceECInstanceId FROM bis.ElementRefersToElements WHERE ECInstanceId=?", (stmt) => {
|
|
376
400
|
stmt.bindId(1, provenanceRelInstanceId);
|
|
377
401
|
nodeAssert(stmt.step() === core_bentley_1.DbResult.BE_SQLITE_ROW);
|
|
@@ -524,9 +548,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
524
548
|
AND Kind=:kind
|
|
525
549
|
LIMIT 1
|
|
526
550
|
`;
|
|
527
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
551
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
528
552
|
const hasConflictingScope = this.provenanceDb.withPreparedStatement(sql,
|
|
529
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
553
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
530
554
|
(statement) => {
|
|
531
555
|
statement.bindId("elementId", aspectProps.element.id);
|
|
532
556
|
statement.bindId("scopeId", aspectProps.scope.id); // this scope.id can never be invalid, we create it above
|
|
@@ -649,9 +673,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
649
673
|
// NOTE: if we exposed the native attach database support,
|
|
650
674
|
// we could get the intersection of fed guids in one query, not sure if it would be faster
|
|
651
675
|
// OR we could do a raw sqlite query...
|
|
652
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
676
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
653
677
|
sourceDb.withStatement(elementIdByFedGuidQuery, (sourceStmt) =>
|
|
654
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
678
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
655
679
|
targetDb.withStatement(elementIdByFedGuidQuery, (targetStmt) => {
|
|
656
680
|
if (sourceStmt.step() !== core_bentley_1.DbResult.BE_SQLITE_ROW)
|
|
657
681
|
return;
|
|
@@ -695,7 +719,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
695
719
|
// Technically this will a second time call the function (as documented) on
|
|
696
720
|
// victims of the old provenance method that have both fedguids and an inserted aspect.
|
|
697
721
|
// But this is a private function with one known caller where that doesn't matter
|
|
698
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
722
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
699
723
|
args.provenanceDb.withPreparedStatement(provenanceAspectsQuery, (stmt) => {
|
|
700
724
|
const runFnInDataFlowDirection = (sourceId, targetId) => args.isReverseSynchronization
|
|
701
725
|
? args.fn(sourceId, targetId)
|
|
@@ -728,7 +752,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
728
752
|
* @returns the elementId that the ESA is stored on, esa.Element.Id
|
|
729
753
|
*/
|
|
730
754
|
_queryProvenanceForElement(entityInProvenanceSourceId) {
|
|
731
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
755
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
732
756
|
return this.provenanceDb.withPreparedStatement(`
|
|
733
757
|
SELECT esa.Element.Id
|
|
734
758
|
FROM Bis.ExternalSourceAspect esa
|
|
@@ -753,7 +777,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
753
777
|
* @returns
|
|
754
778
|
*/
|
|
755
779
|
_queryProvenanceForRelationship(entityInProvenanceSourceId, sourceRelInfo) {
|
|
756
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
780
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
757
781
|
return this.provenanceDb.withPreparedStatement(`
|
|
758
782
|
SELECT
|
|
759
783
|
ECInstanceId,
|
|
@@ -788,7 +812,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
788
812
|
if (targetRelInfo.sourceId === undefined ||
|
|
789
813
|
targetRelInfo.targetId === undefined)
|
|
790
814
|
return undefined; // couldn't find an element, rel is invalid or deleted
|
|
791
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
815
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
792
816
|
return this.targetDb.withPreparedStatement(`
|
|
793
817
|
SELECT ECInstanceId
|
|
794
818
|
FROM bis.ElementRefersToElements
|
|
@@ -816,7 +840,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
816
840
|
// NOTE: this doesn't handle remapped element classes,
|
|
817
841
|
// but is only used for relationships rn
|
|
818
842
|
_getRelClassId(db, classFullName) {
|
|
819
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
843
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
820
844
|
return db.withPreparedStatement(`
|
|
821
845
|
SELECT c.ECInstanceId
|
|
822
846
|
FROM ECDbMeta.ECClassDef c
|
|
@@ -834,7 +858,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
834
858
|
});
|
|
835
859
|
}
|
|
836
860
|
_queryElemIdByFedGuid(db, fedGuid) {
|
|
837
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
861
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
838
862
|
return db.withPreparedStatement("SELECT ECInstanceId FROM Bis.Element WHERE FederationGuid=?", (stmt) => {
|
|
839
863
|
stmt.bindGuid(1, fedGuid);
|
|
840
864
|
if (stmt.step() === core_bentley_1.DbResult.BE_SQLITE_ROW)
|
|
@@ -870,7 +894,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
870
894
|
`;
|
|
871
895
|
nodeAssert(!this.isReverseSynchronization, "synchronizations with processChanges already detect element deletes, don't call detectElementDeletes");
|
|
872
896
|
// Reported issue: https://github.com/iTwin/itwinjs-core/issues/7989
|
|
873
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
897
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
874
898
|
this.provenanceDb.withPreparedStatement(sql, (stmt) => {
|
|
875
899
|
stmt.bindId("scopeId", this.targetScopeElementId);
|
|
876
900
|
stmt.bindString("kind", core_backend_1.ExternalSourceAspect.Kind.Element);
|
|
@@ -918,8 +942,87 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
918
942
|
targetElementProps.jsonProperties.Subject.Job = undefined;
|
|
919
943
|
}
|
|
920
944
|
}
|
|
945
|
+
if (this._linearSpatialTransform !== undefined &&
|
|
946
|
+
sourceElement instanceof core_backend_1.GeometricElement3d) {
|
|
947
|
+
// can check the sourceElement since this IModelTransformer does not remap classes
|
|
948
|
+
const placement = core_common_1.Placement3d.fromJSON(targetElementProps.placement);
|
|
949
|
+
if (placement.isValid) {
|
|
950
|
+
placement.multiplyTransform(this._linearSpatialTransform);
|
|
951
|
+
targetElementProps.placement = placement;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
921
954
|
return targetElementProps;
|
|
922
955
|
}
|
|
956
|
+
/**
|
|
957
|
+
* Calculate the transform between two ECEF locations
|
|
958
|
+
* @param srcDb
|
|
959
|
+
* @param targetDb
|
|
960
|
+
* @returns Transform that converts relative coordinates in the source iModel to relative coordinates in the target iModel.
|
|
961
|
+
* @note This can only be used if both source and target iModels are linearly located
|
|
962
|
+
*/
|
|
963
|
+
calculateEcefTransform() {
|
|
964
|
+
const srcEcefLoc = this.sourceDb.ecefLocation;
|
|
965
|
+
const targetEcefLoc = this.targetDb.ecefLocation;
|
|
966
|
+
if (srcEcefLoc === undefined || targetEcefLoc === undefined) {
|
|
967
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.NoGeoLocation, "Both source and target ECEF locations must be defined to calculate the transform.");
|
|
968
|
+
}
|
|
969
|
+
if (srcEcefLoc.getTransform().isAlmostEqual(targetEcefLoc.getTransform())) {
|
|
970
|
+
core_bentley_1.Logger.logTrace(loggerCategory, "ECEF data is already aligned. No spatial transforms needed.");
|
|
971
|
+
return undefined;
|
|
972
|
+
}
|
|
973
|
+
const srcSpatialToECEF = srcEcefLoc.getTransform(); // converts relative to ECEF in relation to source
|
|
974
|
+
const targetECEFToSpatial = targetEcefLoc.getTransform().inverse(); // converts ECEF to relative in relation to target
|
|
975
|
+
if (!targetECEFToSpatial) {
|
|
976
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.NoGeoLocation, "Failed to invert target ECEF transform.");
|
|
977
|
+
}
|
|
978
|
+
const ecefTransform = targetECEFToSpatial.multiplyTransformTransform(srcSpatialToECEF); // chain both transforms
|
|
979
|
+
return ecefTransform;
|
|
980
|
+
}
|
|
981
|
+
static convertHelmertToTransform(helmert) {
|
|
982
|
+
if (!helmert) {
|
|
983
|
+
return core_geometry_1.Transform.createIdentity();
|
|
984
|
+
}
|
|
985
|
+
const rotationXY = core_geometry_1.Matrix3d.createRotationAroundAxisIndex(core_geometry_1.AxisIndex.Z, core_geometry_1.Angle.createDegrees(helmert?.rotDeg));
|
|
986
|
+
rotationXY.scaleColumnsInPlace(helmert.scale, helmert.scale, 1.0);
|
|
987
|
+
const translation = core_geometry_1.Vector3d.create(helmert.translationX, helmert.translationY, helmert.translationZ);
|
|
988
|
+
const helmertTransform = core_geometry_1.Transform.createRefs(translation, rotationXY);
|
|
989
|
+
return helmertTransform;
|
|
990
|
+
}
|
|
991
|
+
calculateTransformFromHelmertTransforms() {
|
|
992
|
+
if (this.sourceDb.geographicCoordinateSystem?.horizontalCRS === undefined ||
|
|
993
|
+
this.sourceDb.geographicCoordinateSystem?.verticalCRS === undefined) {
|
|
994
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, "Source iModel does not have a geographic coordinate system defined.");
|
|
995
|
+
}
|
|
996
|
+
if (this.targetDb.geographicCoordinateSystem?.horizontalCRS === undefined ||
|
|
997
|
+
this.targetDb.geographicCoordinateSystem.verticalCRS === undefined) {
|
|
998
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadRequest, "Target iModel does not have a geographic coordinate system defined.");
|
|
999
|
+
}
|
|
1000
|
+
if (!this.sourceDb.geographicCoordinateSystem.horizontalCRS.equals(this.targetDb.geographicCoordinateSystem.horizontalCRS) ||
|
|
1001
|
+
!this.sourceDb.geographicCoordinateSystem.verticalCRS.equals(this.targetDb.geographicCoordinateSystem.verticalCRS)) {
|
|
1002
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.MismatchGcs, "Source and target geographic coordinate systems must match to calculate the spatial transform.");
|
|
1003
|
+
}
|
|
1004
|
+
if (this.sourceDb.geographicCoordinateSystem.additionalTransform ===
|
|
1005
|
+
this.targetDb.geographicCoordinateSystem.additionalTransform) {
|
|
1006
|
+
core_bentley_1.Logger.logTrace(loggerCategory, "Geolocation data is already aligned. No spatial transforms needed.");
|
|
1007
|
+
return undefined;
|
|
1008
|
+
}
|
|
1009
|
+
const srcScale = this.sourceDb.geographicCoordinateSystem.additionalTransform
|
|
1010
|
+
?.helmert2DWithZOffset?.scale ?? 1;
|
|
1011
|
+
const targetScale = this.targetDb.geographicCoordinateSystem.additionalTransform
|
|
1012
|
+
?.helmert2DWithZOffset?.scale ?? 1;
|
|
1013
|
+
if (srcScale !== targetScale) {
|
|
1014
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.MismatchGcs, "Spatial transform is non rigid. Source and target Helmert transforms must have the same scale to calculate a rigid spatial transform.");
|
|
1015
|
+
}
|
|
1016
|
+
const srcTransform = IModelTransformer.convertHelmertToTransform(this.sourceDb.geographicCoordinateSystem.additionalTransform
|
|
1017
|
+
?.helmert2DWithZOffset); // moves elements to where src helmert transform would move them at render time
|
|
1018
|
+
const targetTransformInv = IModelTransformer.convertHelmertToTransform(this.targetDb.geographicCoordinateSystem.additionalTransform
|
|
1019
|
+
?.helmert2DWithZOffset).inverse(); // negates target helmert transform that is applied at render time
|
|
1020
|
+
if (!targetTransformInv) {
|
|
1021
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.NoGeoLocation, "Failed to invert target Helmert transform.");
|
|
1022
|
+
}
|
|
1023
|
+
const combinedTransform = targetTransformInv.multiplyTransformTransform(srcTransform);
|
|
1024
|
+
return combinedTransform;
|
|
1025
|
+
}
|
|
923
1026
|
// if undefined, it can be initialized by calling [[this.processChangesets]]
|
|
924
1027
|
_deletedSourceRelationshipData = undefined;
|
|
925
1028
|
/** Returns true if a change within sourceElement is detected.
|
|
@@ -1162,7 +1265,10 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1162
1265
|
if (!this._options.wasSourceIModelCopiedToTarget) {
|
|
1163
1266
|
this.importer.importElement(targetElementProps); // don't need to import if iModel was copied
|
|
1164
1267
|
}
|
|
1165
|
-
|
|
1268
|
+
if (targetElementProps.id === undefined) {
|
|
1269
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadElement, "targetElementProps.id should be assigned by importElement");
|
|
1270
|
+
}
|
|
1271
|
+
this.context.remapElement(sourceElement.id, targetElementProps.id);
|
|
1166
1272
|
// the transformer does not currently 'split' or 'join' any elements, therefore, it does not
|
|
1167
1273
|
// insert external source aspects because federation guids are sufficient for this.
|
|
1168
1274
|
// Other transformer subclasses must insert the appropriate aspect (as provided by a TBD API)
|
|
@@ -1233,7 +1339,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1233
1339
|
WHERE ECInstanceId=:targetModelId
|
|
1234
1340
|
`;
|
|
1235
1341
|
if (this.exporter.sourceDbChanges?.element.deleteIds.has(sourceModelId)) {
|
|
1236
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
1342
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
1237
1343
|
const isDefinitionPartition = this.targetDb.withPreparedStatement(sql, (stmt) => {
|
|
1238
1344
|
stmt.bindId("targetModelId", targetModelId);
|
|
1239
1345
|
const val = stmt.step();
|
|
@@ -1301,9 +1407,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1301
1407
|
await this.initialize();
|
|
1302
1408
|
// import DefinitionModels first
|
|
1303
1409
|
const childDefinitionPartitionSql = `SELECT ECInstanceId FROM ${core_backend_1.DefinitionPartition.classFullName} WHERE Parent.Id=:subjectId`;
|
|
1304
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
1410
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
1305
1411
|
await this.sourceDb.withPreparedStatement(childDefinitionPartitionSql,
|
|
1306
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
1412
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
1307
1413
|
async (statement) => {
|
|
1308
1414
|
statement.bindId("subjectId", sourceSubjectId);
|
|
1309
1415
|
while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
|
|
@@ -1312,9 +1418,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1312
1418
|
});
|
|
1313
1419
|
// import other partitions next
|
|
1314
1420
|
const childPartitionSql = `SELECT ECInstanceId FROM ${core_backend_1.InformationPartitionElement.classFullName} WHERE Parent.Id=:subjectId`;
|
|
1315
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
1421
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
1316
1422
|
await this.sourceDb.withPreparedStatement(childPartitionSql,
|
|
1317
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
1423
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
1318
1424
|
async (statement) => {
|
|
1319
1425
|
statement.bindId("subjectId", sourceSubjectId);
|
|
1320
1426
|
while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
|
|
@@ -1327,9 +1433,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1327
1433
|
});
|
|
1328
1434
|
// recurse into child Subjects
|
|
1329
1435
|
const childSubjectSql = `SELECT ECInstanceId FROM ${core_backend_1.Subject.classFullName} WHERE Parent.Id=:subjectId`;
|
|
1330
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
1436
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
1331
1437
|
await this.sourceDb.withPreparedStatement(childSubjectSql,
|
|
1332
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
1438
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
1333
1439
|
async (statement) => {
|
|
1334
1440
|
statement.bindId("subjectId", sourceSubjectId);
|
|
1335
1441
|
while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
|
|
@@ -1351,6 +1457,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1351
1457
|
id: targetModeledElementId,
|
|
1352
1458
|
};
|
|
1353
1459
|
targetModelProps.id = targetModeledElementId;
|
|
1460
|
+
if (targetModelProps.parentModel === undefined) {
|
|
1461
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadElement, "targetElementProps must have a defined parentModel");
|
|
1462
|
+
}
|
|
1354
1463
|
targetModelProps.parentModel = this.context.findTargetElementId(targetModelProps.parentModel);
|
|
1355
1464
|
return targetModelProps;
|
|
1356
1465
|
}
|
|
@@ -1400,6 +1509,8 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1400
1509
|
(this._startingChangesetIndices && initializeReverseSyncVersion)) {
|
|
1401
1510
|
nodeAssert(this.targetDb.changeset.index !== undefined &&
|
|
1402
1511
|
this._startingChangesetIndices !== undefined, "updateSynchronizationVersion was called without change history");
|
|
1512
|
+
// Store in a local variable, so typescript knows it's defined (due to the assert above)
|
|
1513
|
+
const startingChangesetIndices = this._startingChangesetIndices;
|
|
1403
1514
|
const jsonProps = this._targetScopeProvenanceProps.jsonProperties;
|
|
1404
1515
|
core_bentley_1.Logger.logTrace(loggerCategory, `previous pendingReverseSyncChanges: ${jsonProps.pendingReverseSyncChangesetIndices}`);
|
|
1405
1516
|
core_bentley_1.Logger.logTrace(loggerCategory, `previous pendingSyncChanges: ${jsonProps.pendingSyncChangesetIndices}`);
|
|
@@ -1420,16 +1531,16 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1420
1531
|
// transformation finalization, the work will be saved immediately, otherwise we've
|
|
1421
1532
|
// just marked this changeset as a synchronization to ignore, and the user can add other
|
|
1422
1533
|
// stuff to it which would break future synchronizations
|
|
1423
|
-
for (let i =
|
|
1534
|
+
for (let i = startingChangesetIndices.target + 1; i <= this.targetDb.changeset.index + 1; i++)
|
|
1424
1535
|
jsonProps[syncChangesetsToUpdateKey].push(i);
|
|
1425
1536
|
// Only keep the changeset indices which are greater than the source, this means they haven't been processed yet.
|
|
1426
1537
|
jsonProps[syncChangesetsToClearKey] = jsonProps[syncChangesetsToClearKey].filter((csIndex) => {
|
|
1427
|
-
return csIndex >
|
|
1538
|
+
return csIndex > startingChangesetIndices.source;
|
|
1428
1539
|
});
|
|
1429
1540
|
// if reverse sync then we may have received provenance changes which should be marked as sync changes
|
|
1430
1541
|
if (this.isReverseSynchronization) {
|
|
1431
1542
|
nodeAssert(this.sourceDb.changeset.index !== undefined, "changeset didn't exist");
|
|
1432
|
-
for (let i =
|
|
1543
|
+
for (let i = startingChangesetIndices.source + 1; i <= this.sourceDb.changeset.index + 1; i++)
|
|
1433
1544
|
jsonProps.pendingReverseSyncChangesetIndices.push(i);
|
|
1434
1545
|
}
|
|
1435
1546
|
core_bentley_1.Logger.logTrace(loggerCategory, `new pendingReverseSyncChanges: ${jsonProps.pendingReverseSyncChangesetIndices}`);
|
|
@@ -1551,9 +1662,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1551
1662
|
WHERE aspect.Scope.Id=:scopeId
|
|
1552
1663
|
AND aspect.Kind=:kind
|
|
1553
1664
|
`;
|
|
1554
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
1665
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
1555
1666
|
await this.targetDb.withPreparedStatement(sql,
|
|
1556
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
1667
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
1557
1668
|
async (statement) => {
|
|
1558
1669
|
statement.bindId("scopeId", this.targetScopeElementId);
|
|
1559
1670
|
statement.bindString("kind", core_backend_1.ExternalSourceAspect.Kind.Relationship);
|
|
@@ -1685,7 +1796,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1685
1796
|
nodeAssert(schemaFileName.length <= systemMaxPathSegmentSize, "Schema name was still long. This is a bug.");
|
|
1686
1797
|
this._longNamedSchemasMap.set(schema.name, schemaFileName);
|
|
1687
1798
|
}
|
|
1688
|
-
/* eslint-disable-next-line
|
|
1799
|
+
/* eslint-disable-next-line @typescript-eslint/no-deprecated */
|
|
1689
1800
|
this.sourceDb.exportSchema({
|
|
1690
1801
|
schemaName: schema.name,
|
|
1691
1802
|
outputDirectory: this._schemaExportDir,
|
|
@@ -1848,7 +1959,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1848
1959
|
disableSchemaCheck: true,
|
|
1849
1960
|
});
|
|
1850
1961
|
const csAdaptor = new core_backend_1.ChangesetECAdaptor(csReader);
|
|
1851
|
-
const ecChangeUnifier = new core_backend_1.PartialECChangeUnifier();
|
|
1962
|
+
const ecChangeUnifier = new core_backend_1.PartialECChangeUnifier(this.sourceDb);
|
|
1852
1963
|
while (csAdaptor.step()) {
|
|
1853
1964
|
ecChangeUnifier.appendFrom(csAdaptor);
|
|
1854
1965
|
}
|
|
@@ -1957,7 +2068,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1957
2068
|
const sourceIdOfRelationshipInTarget = await getTargetIdFromSourceId(sourceIdOfRelationshipInSource);
|
|
1958
2069
|
const targetIdOfRelationshipInTarget = await getTargetIdFromSourceId(targetIdOfRelationshipInSource);
|
|
1959
2070
|
if (sourceIdOfRelationshipInTarget && targetIdOfRelationshipInTarget) {
|
|
1960
|
-
this._deletedSourceRelationshipData
|
|
2071
|
+
this._deletedSourceRelationshipData?.set(changedInstanceId, {
|
|
1961
2072
|
classFullName: classFullName ?? "",
|
|
1962
2073
|
sourceIdInTarget: sourceIdOfRelationshipInTarget,
|
|
1963
2074
|
targetIdInTarget: targetIdOfRelationshipInTarget,
|
|
@@ -1970,7 +2081,7 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1970
2081
|
targetId: targetIdOfRelationshipInSource,
|
|
1971
2082
|
});
|
|
1972
2083
|
if (relProvenance && relProvenance.relationshipId)
|
|
1973
|
-
this._deletedSourceRelationshipData
|
|
2084
|
+
this._deletedSourceRelationshipData?.set(changedInstanceId, {
|
|
1974
2085
|
classFullName: classFullName ?? "",
|
|
1975
2086
|
relId: relProvenance.relationshipId,
|
|
1976
2087
|
provenanceAspectId: relProvenance.aspectId,
|
|
@@ -1987,6 +2098,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
1987
2098
|
const deletionNotInTarget = !targetId;
|
|
1988
2099
|
if (deletionNotInTarget)
|
|
1989
2100
|
return;
|
|
2101
|
+
if (targetId === undefined) {
|
|
2102
|
+
throw new core_common_1.IModelError(core_bentley_1.IModelStatus.BadElement, "targetId should aquired from source id or element provenance");
|
|
2103
|
+
}
|
|
1990
2104
|
this.context.remapElement(changedInstanceId, targetId);
|
|
1991
2105
|
// If an entity insert and an entity delete both point to the same entity in target iModel, that means that entity was recreated.
|
|
1992
2106
|
// In such case an entity update will be triggered and we no longer need to delete the entity.
|
|
@@ -2020,13 +2134,11 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2020
2134
|
const endChangesetId = this.sourceDb.changeset.id;
|
|
2021
2135
|
const [startChangesetIndex, endChangesetIndex] = await Promise.all([startChangesetIndexOrId, endChangesetId].map(async (indexOrId) => typeof indexOrId === "number"
|
|
2022
2136
|
? indexOrId
|
|
2023
|
-
: core_backend_1.BriefcaseManager
|
|
2024
|
-
.queryChangeset({
|
|
2137
|
+
: core_backend_1.BriefcaseManager.queryChangeset({
|
|
2025
2138
|
iModelId: this.sourceDb.iModelId,
|
|
2026
|
-
// eslint-disable-next-line
|
|
2139
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
2027
2140
|
changeset: { id: indexOrId },
|
|
2028
|
-
})
|
|
2029
|
-
.then((changeset) => changeset.index)));
|
|
2141
|
+
}).then((changeset) => changeset.index)));
|
|
2030
2142
|
const missingChangesets = startChangesetIndex > this.synchronizationVersion.index + 1;
|
|
2031
2143
|
if (!this._options.argsForProcessChanges
|
|
2032
2144
|
?.ignoreMissingChangesetsInSynchronizations &&
|
|
@@ -2115,9 +2227,9 @@ class IModelTransformer extends IModelExporter_1.IModelExportHandler {
|
|
|
2115
2227
|
await this.exporter.exportRelationships(core_backend_1.ElementRefersToElements.classFullName);
|
|
2116
2228
|
if (this._options.forceExternalSourceAspectProvenance &&
|
|
2117
2229
|
this.shouldDetectDeletes()) {
|
|
2118
|
-
// eslint-disable-next-line
|
|
2230
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
2119
2231
|
await this.detectElementDeletes();
|
|
2120
|
-
// eslint-disable-next-line
|
|
2232
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
2121
2233
|
await this.detectRelationshipDeletes();
|
|
2122
2234
|
}
|
|
2123
2235
|
if (this._options.optimizeGeometry)
|
|
@@ -2294,13 +2406,13 @@ class TemplateModelCloner extends IModelTransformer {
|
|
|
2294
2406
|
targetElementProps.placement = placement;
|
|
2295
2407
|
}
|
|
2296
2408
|
}
|
|
2297
|
-
this._sourceIdToTargetIdMap
|
|
2409
|
+
this._sourceIdToTargetIdMap?.set(sourceElement.id, core_bentley_1.Id64.invalid); // keep track of (source) elementIds from the template model, but the target hasn't been inserted yet
|
|
2298
2410
|
return targetElementProps;
|
|
2299
2411
|
}
|
|
2300
2412
|
}
|
|
2301
2413
|
exports.TemplateModelCloner = TemplateModelCloner;
|
|
2302
2414
|
function queryElemFedGuid(db, elemId) {
|
|
2303
|
-
// eslint-disable-next-line @itwin/no-internal,
|
|
2415
|
+
// eslint-disable-next-line @itwin/no-internal, @typescript-eslint/no-deprecated
|
|
2304
2416
|
return db.withPreparedStatement(`
|
|
2305
2417
|
SELECT FederationGuid
|
|
2306
2418
|
FROM bis.Element
|