@itwin/imodel-transformer 0.4.18-fedguidopt.6 → 1.0.1-dev.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/lib/cjs/Algo.d.ts.map +1 -1
- package/lib/cjs/Algo.js +3 -4
- package/lib/cjs/Algo.js.map +1 -1
- package/lib/cjs/BigMap.d.ts.map +1 -1
- package/lib/cjs/BigMap.js +1 -1
- package/lib/cjs/BigMap.js.map +1 -1
- package/lib/cjs/BranchProvenanceInitializer.d.ts.map +1 -1
- package/lib/cjs/BranchProvenanceInitializer.js +15 -4
- package/lib/cjs/BranchProvenanceInitializer.js.map +1 -1
- package/lib/cjs/DetachedExportElementAspectsStrategy.d.ts.map +1 -1
- package/lib/cjs/DetachedExportElementAspectsStrategy.js +12 -5
- package/lib/cjs/DetachedExportElementAspectsStrategy.js.map +1 -1
- package/lib/cjs/ECReferenceTypesCache.d.ts.map +1 -1
- package/lib/cjs/ECReferenceTypesCache.js +32 -18
- package/lib/cjs/ECReferenceTypesCache.js.map +1 -1
- package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.d.ts +1 -1
- package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.d.ts.map +1 -1
- package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.js +7 -5
- package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.js.map +1 -1
- package/lib/cjs/ElementCascadingDeleter.d.ts +3 -3
- package/lib/cjs/ElementCascadingDeleter.d.ts.map +1 -1
- package/lib/cjs/ElementCascadingDeleter.js +9 -7
- package/lib/cjs/ElementCascadingDeleter.js.map +1 -1
- package/lib/cjs/EntityMap.d.ts.map +1 -1
- package/lib/cjs/EntityMap.js.map +1 -1
- package/lib/cjs/EntityUnifier.d.ts +5 -0
- package/lib/cjs/EntityUnifier.d.ts.map +1 -1
- package/lib/cjs/EntityUnifier.js +22 -35
- package/lib/cjs/EntityUnifier.js.map +1 -1
- package/lib/cjs/ExportElementAspectsStrategy.d.ts.map +1 -1
- package/lib/cjs/ExportElementAspectsStrategy.js +5 -4
- package/lib/cjs/ExportElementAspectsStrategy.js.map +1 -1
- package/lib/cjs/ExportElementAspectsWithElementsStrategy.d.ts.map +1 -1
- package/lib/cjs/ExportElementAspectsWithElementsStrategy.js +9 -5
- package/lib/cjs/ExportElementAspectsWithElementsStrategy.js.map +1 -1
- package/lib/cjs/IModelCloneContext.d.ts.map +1 -1
- package/lib/cjs/IModelCloneContext.js +23 -12
- package/lib/cjs/IModelCloneContext.js.map +1 -1
- package/lib/cjs/IModelExporter.d.ts +68 -25
- package/lib/cjs/IModelExporter.d.ts.map +1 -1
- package/lib/cjs/IModelExporter.js +241 -123
- package/lib/cjs/IModelExporter.js.map +1 -1
- package/lib/cjs/IModelImporter.d.ts +13 -22
- package/lib/cjs/IModelImporter.d.ts.map +1 -1
- package/lib/cjs/IModelImporter.js +80 -62
- package/lib/cjs/IModelImporter.js.map +1 -1
- package/lib/cjs/IModelTransformer.d.ts +126 -44
- package/lib/cjs/IModelTransformer.d.ts.map +1 -1
- package/lib/cjs/IModelTransformer.js +706 -535
- package/lib/cjs/IModelTransformer.js.map +1 -1
- package/lib/cjs/PendingReferenceMap.d.ts.map +1 -1
- package/lib/cjs/PendingReferenceMap.js +12 -6
- package/lib/cjs/PendingReferenceMap.js.map +1 -1
- package/lib/cjs/TransformerLoggerCategory.d.ts +2 -2
- package/lib/cjs/TransformerLoggerCategory.d.ts.map +1 -1
- package/lib/cjs/TransformerLoggerCategory.js +5 -5
- package/lib/cjs/TransformerLoggerCategory.js.map +1 -1
- package/lib/cjs/transformer.d.ts.map +1 -1
- package/lib/cjs/transformer.js +14 -10
- package/lib/cjs/transformer.js.map +1 -1
- package/package.json +20 -17
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*---------------------------------------------------------------------------------------------
|
|
3
|
-
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
-
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
-
*--------------------------------------------------------------------------------------------*/
|
|
3
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
4
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
5
|
+
*--------------------------------------------------------------------------------------------*/
|
|
6
6
|
/** @packageDocumentation
|
|
7
7
|
* @module iModels
|
|
8
8
|
*/
|
|
@@ -26,7 +26,9 @@ class IModelExportHandler {
|
|
|
26
26
|
/** If `true` is returned, then the CodeSpec will be exported.
|
|
27
27
|
* @note This method can optionally be overridden to exclude an individual CodeSpec from the export. The base implementation always returns `true`.
|
|
28
28
|
*/
|
|
29
|
-
shouldExportCodeSpec(_codeSpec) {
|
|
29
|
+
shouldExportCodeSpec(_codeSpec) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
30
32
|
/** Called when a CodeSpec should be exported.
|
|
31
33
|
* @param codeSpec The CodeSpec to export
|
|
32
34
|
* @param isUpdate If defined, then `true` indicates an UPDATE operation while `false` indicates an INSERT operation. If not defined, then INSERT vs. UPDATE is not known.
|
|
@@ -50,7 +52,9 @@ class IModelExportHandler {
|
|
|
50
52
|
/** If `true` is returned, then the element will be exported.
|
|
51
53
|
* @note This method can optionally be overridden to exclude an individual Element (and its children and ElementAspects) from the export. The base implementation always returns `true`.
|
|
52
54
|
*/
|
|
53
|
-
shouldExportElement(_element) {
|
|
55
|
+
shouldExportElement(_element) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
54
58
|
/** Called when element is skipped instead of exported. */
|
|
55
59
|
onSkipElement(_elementId) { }
|
|
56
60
|
/** Called when an element should be exported.
|
|
@@ -71,7 +75,9 @@ class IModelExportHandler {
|
|
|
71
75
|
/** If `true` is returned, then the ElementAspect will be exported.
|
|
72
76
|
* @note This method can optionally be overridden to exclude an individual ElementAspect from the export. The base implementation always returns `true`.
|
|
73
77
|
*/
|
|
74
|
-
shouldExportElementAspect(_aspect) {
|
|
78
|
+
shouldExportElementAspect(_aspect) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
75
81
|
/** Called when an ElementUniqueAspect should be exported.
|
|
76
82
|
* @param aspect The ElementUniqueAspect to export
|
|
77
83
|
* @param isUpdate If defined, then `true` indicates an UPDATE operation while `false` indicates an INSERT operation. If not defined, then INSERT vs. UPDATE is not known.
|
|
@@ -85,7 +91,9 @@ class IModelExportHandler {
|
|
|
85
91
|
/** If `true` is returned, then the relationship will be exported.
|
|
86
92
|
* @note This method can optionally be overridden to exclude an individual CodeSpec from the export. The base implementation always returns `true`.
|
|
87
93
|
*/
|
|
88
|
-
shouldExportRelationship(_relationship) {
|
|
94
|
+
shouldExportRelationship(_relationship) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
89
97
|
/** Called when a Relationship should be exported.
|
|
90
98
|
* @param relationship The Relationship to export
|
|
91
99
|
* @param isUpdate If defined, then `true` indicates an UPDATE operation while `false` indicates an INSERT operation. If not defined, then INSERT vs. UPDATE is not known.
|
|
@@ -97,7 +105,9 @@ class IModelExportHandler {
|
|
|
97
105
|
/** If `true` is returned, then the schema will be exported.
|
|
98
106
|
* @note This method can optionally be overridden to exclude an individual schema from the export. The base implementation always returns `true`.
|
|
99
107
|
*/
|
|
100
|
-
shouldExportSchema(_schemaKey) {
|
|
108
|
+
shouldExportSchema(_schemaKey) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
101
111
|
/** Called when a schema should be exported.
|
|
102
112
|
* @param schema The schema to export
|
|
103
113
|
* @note This should be overridden to actually do the export.
|
|
@@ -121,7 +131,7 @@ class IModelExporter {
|
|
|
121
131
|
/**
|
|
122
132
|
* Retrieve the cached entity change information.
|
|
123
133
|
* @note This will only be initialized after [IModelExporter.exportChanges] is invoked.
|
|
124
|
-
|
|
134
|
+
*/
|
|
125
135
|
get sourceDbChanges() {
|
|
126
136
|
return this._sourceDbChanges;
|
|
127
137
|
}
|
|
@@ -194,11 +204,14 @@ class IModelExporter {
|
|
|
194
204
|
* you pass to [[IModelExporter.exportChanges]]
|
|
195
205
|
*/
|
|
196
206
|
async initialize(options) {
|
|
197
|
-
|
|
198
|
-
|
|
207
|
+
if (!this.sourceDb.isBriefcaseDb() || this._sourceDbChanges)
|
|
208
|
+
return;
|
|
209
|
+
this._sourceDbChanges = await ChangedInstanceIds.initialize({
|
|
210
|
+
iModel: this.sourceDb,
|
|
211
|
+
...options,
|
|
212
|
+
});
|
|
213
|
+
if (this._sourceDbChanges === undefined)
|
|
199
214
|
return;
|
|
200
|
-
this._sourceDbChanges = options.changedInstanceIds
|
|
201
|
-
?? await ChangedInstanceIds.initialize({ iModel: this.sourceDb, ...options });
|
|
202
215
|
this._exportElementAspectsStrategy.setAspectChanges(this._sourceDbChanges.aspect);
|
|
203
216
|
}
|
|
204
217
|
/** Register the handler that will be called by IModelExporter. */
|
|
@@ -257,8 +270,13 @@ class IModelExporter {
|
|
|
257
270
|
nodeAssert(this._sourceDbChanges !== undefined, "sourceDbChanges must be initialized.");
|
|
258
271
|
await this.exportCodeSpecs();
|
|
259
272
|
await this.exportFonts();
|
|
260
|
-
|
|
261
|
-
|
|
273
|
+
if (initOpts.skipPropagateChangesToRootElements) {
|
|
274
|
+
await this.exportModelContents(core_common_1.IModel.repositoryModelId);
|
|
275
|
+
await this.exportSubModels(core_common_1.IModel.repositoryModelId);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
await this.exportModel(core_common_1.IModel.repositoryModelId);
|
|
279
|
+
}
|
|
262
280
|
await this.exportAllAspects();
|
|
263
281
|
await this.exportRelationships(core_backend_1.ElementRefersToElements.classFullName);
|
|
264
282
|
// handle deletes
|
|
@@ -278,14 +296,16 @@ class IModelExporter {
|
|
|
278
296
|
this.handler.onDeleteElement(elementId);
|
|
279
297
|
}
|
|
280
298
|
catch (err) {
|
|
281
|
-
const isMissingErr = err instanceof core_common_1.IModelError &&
|
|
299
|
+
const isMissingErr = err instanceof core_common_1.IModelError &&
|
|
300
|
+
err.errorNumber === core_bentley_1.IModelStatus.NotFound;
|
|
282
301
|
if (!isMissingErr)
|
|
283
302
|
throw err;
|
|
284
303
|
}
|
|
285
304
|
}
|
|
286
305
|
}
|
|
287
306
|
if (this.visitRelationships) {
|
|
288
|
-
for (const relInstanceId of this._sourceDbChanges.relationship
|
|
307
|
+
for (const relInstanceId of this._sourceDbChanges.relationship
|
|
308
|
+
.deleteIds) {
|
|
289
309
|
this.handler.onDeleteRelationship(relInstanceId);
|
|
290
310
|
}
|
|
291
311
|
}
|
|
@@ -304,7 +324,9 @@ class IModelExporter {
|
|
|
304
324
|
const sql = `
|
|
305
325
|
SELECT s.Name, s.VersionMajor, s.VersionWrite, s.VersionMinor
|
|
306
326
|
FROM ECDbMeta.ECSchemaDef s
|
|
307
|
-
${this.wantSystemSchemas
|
|
327
|
+
${this.wantSystemSchemas
|
|
328
|
+
? ""
|
|
329
|
+
: `
|
|
308
330
|
WHERE ECInstanceId >= (SELECT ECInstanceId FROM ECDbMeta.ECSchemaDef WHERE Name='BisCore')
|
|
309
331
|
`}
|
|
310
332
|
ORDER BY ECInstanceId
|
|
@@ -340,8 +362,8 @@ class IModelExporter {
|
|
|
340
362
|
* @note This method is called from [[exportChanges]] and [[exportAll]], so it only needs to be called directly when exporting a subset of an iModel.
|
|
341
363
|
*/
|
|
342
364
|
async exportCodeSpecs() {
|
|
343
|
-
core_bentley_1.Logger.logTrace(loggerCategory,
|
|
344
|
-
const sql =
|
|
365
|
+
core_bentley_1.Logger.logTrace(loggerCategory, "exportCodeSpecs()");
|
|
366
|
+
const sql = "SELECT Name FROM BisCore:CodeSpec ORDER BY ECInstanceId";
|
|
345
367
|
await this.sourceDb.withPreparedStatement(sql, async (statement) => {
|
|
346
368
|
while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
|
|
347
369
|
const codeSpecName = statement.getValue(0).getString();
|
|
@@ -355,7 +377,8 @@ class IModelExporter {
|
|
|
355
377
|
async exportCodeSpecByName(codeSpecName) {
|
|
356
378
|
const codeSpec = this.sourceDb.codeSpecs.getByName(codeSpecName);
|
|
357
379
|
let isUpdate;
|
|
358
|
-
if (undefined !== this._sourceDbChanges) {
|
|
380
|
+
if (undefined !== this._sourceDbChanges) {
|
|
381
|
+
// is changeset information available?
|
|
359
382
|
if (this._sourceDbChanges.codeSpec.insertIds.has(codeSpec.id)) {
|
|
360
383
|
isUpdate = false;
|
|
361
384
|
}
|
|
@@ -389,7 +412,7 @@ class IModelExporter {
|
|
|
389
412
|
* @note This method is called from [[exportChanges]] and [[exportAll]], so it only needs to be called directly when exporting a subset of an iModel.
|
|
390
413
|
*/
|
|
391
414
|
async exportFonts() {
|
|
392
|
-
core_bentley_1.Logger.logTrace(loggerCategory,
|
|
415
|
+
core_bentley_1.Logger.logTrace(loggerCategory, "exportFonts()");
|
|
393
416
|
for (const font of this.sourceDb.fontMap.fonts.values()) {
|
|
394
417
|
await this.exportFontByNumber(font.id);
|
|
395
418
|
}
|
|
@@ -408,19 +431,12 @@ class IModelExporter {
|
|
|
408
431
|
* @note This method is called from [[exportChanges]] and [[exportAll]], so it only needs to be called directly when exporting a subset of an iModel.
|
|
409
432
|
*/
|
|
410
433
|
async exportFontByNumber(fontNumber) {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
else if (this._sourceDbChanges.font.updateIds.has(fontId)) {
|
|
418
|
-
isUpdate = true;
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
return; // not in changeset, don't export
|
|
422
|
-
}
|
|
423
|
-
}
|
|
434
|
+
/** sourceDbChanges now works by using TS ChangesetECAdaptor which doesn't pick up changes to fonts since fonts is not an ec table.
|
|
435
|
+
* So lets always export fonts for the time being by always setting isUpdate = true.
|
|
436
|
+
* It is very rare and even problematic for the font table to reach a large size, so it is not a bottleneck in transforming changes.
|
|
437
|
+
* See https://github.com/iTwin/imodel-transformer/pull/135 for removed code.
|
|
438
|
+
*/
|
|
439
|
+
const isUpdate = true;
|
|
424
440
|
core_bentley_1.Logger.logTrace(loggerCategory, `exportFontById(${fontNumber})`);
|
|
425
441
|
const font = this.sourceDb.fontMap.getFont(fontNumber);
|
|
426
442
|
if (undefined !== font) {
|
|
@@ -436,7 +452,11 @@ class IModelExporter {
|
|
|
436
452
|
if (model.isTemplate && !this.wantTemplateModels) {
|
|
437
453
|
return;
|
|
438
454
|
}
|
|
439
|
-
const modeledElement = this.sourceDb.elements.getElement({
|
|
455
|
+
const modeledElement = this.sourceDb.elements.getElement({
|
|
456
|
+
id: modeledElementId,
|
|
457
|
+
wantGeometry: this.wantGeometry,
|
|
458
|
+
wantBRepData: this.wantGeometry,
|
|
459
|
+
});
|
|
440
460
|
core_bentley_1.Logger.logTrace(loggerCategory, `exportModel(${modeledElementId})`);
|
|
441
461
|
if (this.shouldExportElement(modeledElement)) {
|
|
442
462
|
await this.exportModelContainer(model);
|
|
@@ -449,7 +469,8 @@ class IModelExporter {
|
|
|
449
469
|
/** Export the model (the container only) from the source iModel. */
|
|
450
470
|
async exportModelContainer(model) {
|
|
451
471
|
let isUpdate;
|
|
452
|
-
if (undefined !== this._sourceDbChanges) {
|
|
472
|
+
if (undefined !== this._sourceDbChanges) {
|
|
473
|
+
// is changeset information available?
|
|
453
474
|
if (this._sourceDbChanges.model.insertIds.has(model.id)) {
|
|
454
475
|
isUpdate = false;
|
|
455
476
|
}
|
|
@@ -479,8 +500,10 @@ class IModelExporter {
|
|
|
479
500
|
core_bentley_1.Logger.logTrace(loggerCategory, `visitElements=false, skipping exportModelContents(${modelId})`);
|
|
480
501
|
return;
|
|
481
502
|
}
|
|
482
|
-
if (undefined !== this._sourceDbChanges) {
|
|
483
|
-
|
|
503
|
+
if (undefined !== this._sourceDbChanges) {
|
|
504
|
+
// is changeset information available?
|
|
505
|
+
if (!this._sourceDbChanges.model.insertIds.has(modelId) &&
|
|
506
|
+
!this._sourceDbChanges.model.updateIds.has(modelId)) {
|
|
484
507
|
return; // this optimization assumes that the Model changes (LastMod) any time an Element in the Model changes
|
|
485
508
|
}
|
|
486
509
|
}
|
|
@@ -547,7 +570,8 @@ class IModelExporter {
|
|
|
547
570
|
return false;
|
|
548
571
|
}
|
|
549
572
|
}
|
|
550
|
-
if (!this.wantTemplateModels &&
|
|
573
|
+
if (!this.wantTemplateModels &&
|
|
574
|
+
element instanceof core_backend_1.RecipeDefinitionElement) {
|
|
551
575
|
core_bentley_1.Logger.logInfo(loggerCategory, `Excluded RecipeDefinitionElement ${element.id} because wantTemplate=false`);
|
|
552
576
|
return false;
|
|
553
577
|
}
|
|
@@ -569,10 +593,16 @@ class IModelExporter {
|
|
|
569
593
|
return;
|
|
570
594
|
}
|
|
571
595
|
// are we processing changes?
|
|
572
|
-
const isUpdate = this._sourceDbChanges?.element.insertIds.has(elementId)
|
|
573
|
-
|
|
596
|
+
const isUpdate = this._sourceDbChanges?.element.insertIds.has(elementId)
|
|
597
|
+
? false
|
|
598
|
+
: this._sourceDbChanges?.element.updateIds.has(elementId)
|
|
599
|
+
? true
|
|
574
600
|
: undefined;
|
|
575
|
-
const element = this.sourceDb.elements.getElement({
|
|
601
|
+
const element = this.sourceDb.elements.getElement({
|
|
602
|
+
id: elementId,
|
|
603
|
+
wantGeometry: this.wantGeometry,
|
|
604
|
+
wantBRepData: this.wantGeometry,
|
|
605
|
+
});
|
|
576
606
|
core_bentley_1.Logger.logTrace(loggerCategory, `exportElement(${element.id}, "${element.getDisplayLabel()}")${this.getChangeOpSuffix(isUpdate)}`);
|
|
577
607
|
// the order and `await`ing of calls beyond here is depended upon by the IModelTransformer for a current bug workaround
|
|
578
608
|
if (this.shouldExportElement(element)) {
|
|
@@ -612,7 +642,7 @@ class IModelExporter {
|
|
|
612
642
|
*/
|
|
613
643
|
async exportRelationships(baseRelClassFullName) {
|
|
614
644
|
if (!this.visitRelationships) {
|
|
615
|
-
core_bentley_1.Logger.logTrace(loggerCategory,
|
|
645
|
+
core_bentley_1.Logger.logTrace(loggerCategory, "visitRelationships=false, skipping exportRelationships()");
|
|
616
646
|
return;
|
|
617
647
|
}
|
|
618
648
|
core_bentley_1.Logger.logTrace(loggerCategory, `exportRelationships(${baseRelClassFullName})`);
|
|
@@ -623,7 +653,9 @@ class IModelExporter {
|
|
|
623
653
|
await this.sourceDb.withPreparedStatement(sql, async (statement) => {
|
|
624
654
|
while (core_bentley_1.DbResult.BE_SQLITE_ROW === statement.step()) {
|
|
625
655
|
const relationshipId = statement.getValue(0).getId();
|
|
626
|
-
const relationshipClass = statement
|
|
656
|
+
const relationshipClass = statement
|
|
657
|
+
.getValue(1)
|
|
658
|
+
.getClassNameForClassId();
|
|
627
659
|
await this.exportRelationship(relationshipClass, relationshipId); // must call exportRelationship using the actual classFullName, not baseRelClassFullName
|
|
628
660
|
await this._yieldManager.allowYield();
|
|
629
661
|
}
|
|
@@ -636,7 +668,8 @@ class IModelExporter {
|
|
|
636
668
|
return;
|
|
637
669
|
}
|
|
638
670
|
let isUpdate;
|
|
639
|
-
if (undefined !== this._sourceDbChanges) {
|
|
671
|
+
if (undefined !== this._sourceDbChanges) {
|
|
672
|
+
// is changeset information available?
|
|
640
673
|
if (this._sourceDbChanges.relationship.insertIds.has(relInstanceId)) {
|
|
641
674
|
isUpdate = false;
|
|
642
675
|
}
|
|
@@ -665,7 +698,7 @@ class IModelExporter {
|
|
|
665
698
|
/** Tracks incremental progress */
|
|
666
699
|
async trackProgress() {
|
|
667
700
|
this._progressCounter++;
|
|
668
|
-
if (0 ===
|
|
701
|
+
if (0 === this._progressCounter % this.progressInterval) {
|
|
669
702
|
return this.handler.onProgress();
|
|
670
703
|
}
|
|
671
704
|
}
|
|
@@ -696,9 +729,9 @@ class IModelExporter {
|
|
|
696
729
|
this.visitElements = state.visitElements;
|
|
697
730
|
this.visitRelationships = state.visitRelationships;
|
|
698
731
|
this._excludedCodeSpecNames = new Set(state.excludedCodeSpecNames);
|
|
699
|
-
this._excludedElementIds = core_bentley_1.CompressedId64Set.decompressSet(state.excludedElementIds),
|
|
700
|
-
this._excludedElementCategoryIds = core_bentley_1.CompressedId64Set.decompressSet(state.excludedElementCategoryIds),
|
|
701
|
-
this._excludedElementClasses = new Set(state.excludedElementClassNames.map((c) => this.sourceDb.getJsClass(c)));
|
|
732
|
+
(this._excludedElementIds = core_bentley_1.CompressedId64Set.decompressSet(state.excludedElementIds)),
|
|
733
|
+
(this._excludedElementCategoryIds = core_bentley_1.CompressedId64Set.decompressSet(state.excludedElementCategoryIds)),
|
|
734
|
+
(this._excludedElementClasses = new Set(state.excludedElementClassNames.map((c) => this.sourceDb.getJsClass(c))));
|
|
702
735
|
this._exportElementAspectsStrategy.loadExcludedElementAspectClasses(state.excludedElementAspectClassFullNames);
|
|
703
736
|
this._excludedRelationshipClasses = new Set(state.excludedRelationshipClassNames.map((c) => this.sourceDb.getJsClass(c)));
|
|
704
737
|
this.loadAdditionalStateJson(state.additionalState);
|
|
@@ -721,39 +754,19 @@ class IModelExporter {
|
|
|
721
754
|
excludedElementIds: core_bentley_1.CompressedId64Set.compressSet(this._excludedElementIds),
|
|
722
755
|
excludedElementCategoryIds: core_bentley_1.CompressedId64Set.compressSet(this._excludedElementCategoryIds),
|
|
723
756
|
excludedElementClassNames: Array.from(this._excludedElementClasses, (cls) => cls.classFullName),
|
|
724
|
-
excludedElementAspectClassFullNames: [
|
|
757
|
+
excludedElementAspectClassFullNames: [
|
|
758
|
+
...this._exportElementAspectsStrategy
|
|
759
|
+
.excludedElementAspectClassFullNames,
|
|
760
|
+
],
|
|
725
761
|
excludedRelationshipClassNames: Array.from(this._excludedRelationshipClasses, (cls) => cls.classFullName),
|
|
726
762
|
additionalState: this.getAdditionalStateJson(),
|
|
727
763
|
};
|
|
728
764
|
}
|
|
729
765
|
}
|
|
730
766
|
exports.IModelExporter = IModelExporter;
|
|
731
|
-
/**
|
|
732
|
-
* Asserts that the passed in options have exactly one of:
|
|
733
|
-
* startChangeset xor changesetRanges xor changedInstanceIds
|
|
734
|
-
* defined
|
|
735
|
-
*/
|
|
736
|
-
function assertHasChangeDataOptions(opts) {
|
|
737
|
-
const xor = (...args) => {
|
|
738
|
-
let result = false;
|
|
739
|
-
for (const a of args) {
|
|
740
|
-
if (!result && a)
|
|
741
|
-
result = true;
|
|
742
|
-
else if (result && a)
|
|
743
|
-
return false;
|
|
744
|
-
}
|
|
745
|
-
return result;
|
|
746
|
-
};
|
|
747
|
-
nodeAssert(xor(opts.startChangeset, opts.changesetRanges, opts.changedInstanceIds), "exactly one of startChangeset, XOR changesetRanges XOR opts.changedInstanceIds may be defined but "
|
|
748
|
-
+ `received ${JSON.stringify({
|
|
749
|
-
startChangeset: !!opts.startChangeset,
|
|
750
|
-
changesetRanges: !!opts.changesetRanges,
|
|
751
|
-
ChangedInstanceIds: !!opts.changedInstanceIds,
|
|
752
|
-
})}`);
|
|
753
|
-
}
|
|
754
767
|
/** Class for holding change information.
|
|
755
768
|
* @beta
|
|
756
|
-
*/
|
|
769
|
+
*/
|
|
757
770
|
class ChangedInstanceOps {
|
|
758
771
|
constructor() {
|
|
759
772
|
this.insertIds = new Set();
|
|
@@ -763,11 +776,11 @@ class ChangedInstanceOps {
|
|
|
763
776
|
/** Initializes the object from IModelJsNative.ChangedInstanceOpsProps. */
|
|
764
777
|
addFromJson(val) {
|
|
765
778
|
if (undefined !== val) {
|
|
766
|
-
if (
|
|
779
|
+
if (undefined !== val.insert && Array.isArray(val.insert))
|
|
767
780
|
val.insert.forEach((id) => this.insertIds.add(id));
|
|
768
|
-
if (
|
|
781
|
+
if (undefined !== val.update && Array.isArray(val.update))
|
|
769
782
|
val.update.forEach((id) => this.updateIds.add(id));
|
|
770
|
-
if (
|
|
783
|
+
if (undefined !== val.delete && Array.isArray(val.delete))
|
|
771
784
|
val.delete.forEach((id) => this.deleteIds.add(id));
|
|
772
785
|
}
|
|
773
786
|
}
|
|
@@ -778,69 +791,174 @@ exports.ChangedInstanceOps = ChangedInstanceOps;
|
|
|
778
791
|
* @beta
|
|
779
792
|
*/
|
|
780
793
|
class ChangedInstanceIds {
|
|
781
|
-
constructor() {
|
|
794
|
+
constructor(db) {
|
|
782
795
|
this.codeSpec = new ChangedInstanceOps();
|
|
783
796
|
this.model = new ChangedInstanceOps();
|
|
784
797
|
this.element = new ChangedInstanceOps();
|
|
785
798
|
this.aspect = new ChangedInstanceOps();
|
|
786
799
|
this.relationship = new ChangedInstanceOps();
|
|
787
800
|
this.font = new ChangedInstanceOps();
|
|
801
|
+
this._db = db;
|
|
802
|
+
}
|
|
803
|
+
async setupECClassIds() {
|
|
804
|
+
this._codeSpecSubclassIds = new Set();
|
|
805
|
+
this._modelSubclassIds = new Set();
|
|
806
|
+
this._elementSubclassIds = new Set();
|
|
807
|
+
this._aspectSubclassIds = new Set();
|
|
808
|
+
this._relationshipSubclassIds = new Set();
|
|
809
|
+
const addECClassIdsToSet = async (setToModify, baseClass) => {
|
|
810
|
+
for await (const row of this._db.createQueryReader(`SELECT ECInstanceId FROM ECDbMeta.ECClassDef where ECInstanceId IS (${baseClass})`)) {
|
|
811
|
+
setToModify.add(row.ECInstanceId);
|
|
812
|
+
}
|
|
813
|
+
};
|
|
814
|
+
const promises = [
|
|
815
|
+
addECClassIdsToSet(this._codeSpecSubclassIds, "BisCore.CodeSpec"),
|
|
816
|
+
addECClassIdsToSet(this._modelSubclassIds, "BisCore.Model"),
|
|
817
|
+
addECClassIdsToSet(this._elementSubclassIds, "BisCore.Element"),
|
|
818
|
+
addECClassIdsToSet(this._aspectSubclassIds, "BisCore.ElementUniqueAspect"),
|
|
819
|
+
addECClassIdsToSet(this._aspectSubclassIds, "BisCore.ElementMultiAspect"),
|
|
820
|
+
addECClassIdsToSet(this._relationshipSubclassIds, "BisCore.ElementRefersToElements"),
|
|
821
|
+
];
|
|
822
|
+
await Promise.all(promises);
|
|
823
|
+
}
|
|
824
|
+
get _ecClassIdsInitialized() {
|
|
825
|
+
return (this._codeSpecSubclassIds &&
|
|
826
|
+
this._modelSubclassIds &&
|
|
827
|
+
this._elementSubclassIds &&
|
|
828
|
+
this._aspectSubclassIds &&
|
|
829
|
+
this._relationshipSubclassIds);
|
|
830
|
+
}
|
|
831
|
+
isRelationship(ecClassId) {
|
|
832
|
+
return this._relationshipSubclassIds?.has(ecClassId);
|
|
833
|
+
}
|
|
834
|
+
isCodeSpec(ecClassId) {
|
|
835
|
+
return this._codeSpecSubclassIds?.has(ecClassId);
|
|
836
|
+
}
|
|
837
|
+
isAspect(ecClassId) {
|
|
838
|
+
return this._aspectSubclassIds?.has(ecClassId);
|
|
839
|
+
}
|
|
840
|
+
isModel(ecClassId) {
|
|
841
|
+
return this._modelSubclassIds?.has(ecClassId);
|
|
842
|
+
}
|
|
843
|
+
isElement(ecClassId) {
|
|
844
|
+
return this._elementSubclassIds?.has(ecClassId);
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* 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.
|
|
848
|
+
* 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'
|
|
849
|
+
* from the set of updatedIds and add it to the set of deletedIds for the appropriate class type.
|
|
850
|
+
* @param change ChangedECInstance which has the ECInstanceId, changeType (insert, update, delete) and ECClassId of the changed entity
|
|
851
|
+
*/
|
|
852
|
+
async addChange(change) {
|
|
853
|
+
if (!this._ecClassIdsInitialized)
|
|
854
|
+
await this.setupECClassIds();
|
|
855
|
+
const ecClassId = change.ECClassId ?? change.$meta?.fallbackClassId;
|
|
856
|
+
if (ecClassId === undefined)
|
|
857
|
+
throw new Error(`ECClassId was not found for id: ${change.ECInstanceId}! Table is : ${change?.$meta?.tables}`);
|
|
858
|
+
const changeType = change.$meta?.op;
|
|
859
|
+
if (changeType === undefined)
|
|
860
|
+
throw new Error(`ChangeType was undefined for id: ${change.ECInstanceId}.`);
|
|
861
|
+
if (this.isRelationship(ecClassId))
|
|
862
|
+
this.handleChange(this.relationship, changeType, change.ECInstanceId);
|
|
863
|
+
else if (this.isCodeSpec(ecClassId))
|
|
864
|
+
this.handleChange(this.codeSpec, changeType, change.ECInstanceId);
|
|
865
|
+
else if (this.isAspect(ecClassId))
|
|
866
|
+
this.handleChange(this.aspect, changeType, change.ECInstanceId);
|
|
867
|
+
else if (this.isModel(ecClassId))
|
|
868
|
+
this.handleChange(this.model, changeType, change.ECInstanceId);
|
|
869
|
+
else if (this.isElement(ecClassId))
|
|
870
|
+
this.handleChange(this.element, changeType, change.ECInstanceId);
|
|
871
|
+
}
|
|
872
|
+
handleChange(changedInstanceOps, changeType, id) {
|
|
873
|
+
// if changeType is a delete and we already have the id in the inserts then we can remove the id from the inserts.
|
|
874
|
+
// 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.
|
|
875
|
+
// if changeType is an insert and we already have the id in the deletes then we can remove the id from the deletes AND add it to the inserts.
|
|
876
|
+
if (changeType === "Inserted") {
|
|
877
|
+
changedInstanceOps.insertIds.add(id);
|
|
878
|
+
changedInstanceOps.deleteIds.delete(id);
|
|
879
|
+
}
|
|
880
|
+
else if (changeType === "Updated") {
|
|
881
|
+
if (!changedInstanceOps.insertIds.has(id))
|
|
882
|
+
changedInstanceOps.updateIds.add(id);
|
|
883
|
+
}
|
|
884
|
+
else if (changeType === "Deleted") {
|
|
885
|
+
// If we've inserted the entity at some point already and now we're seeing a delete. We can simply remove the entity from our inserted ids without adding it to deletedIds.
|
|
886
|
+
if (changedInstanceOps.insertIds.has(id))
|
|
887
|
+
changedInstanceOps.insertIds.delete(id);
|
|
888
|
+
else {
|
|
889
|
+
changedInstanceOps.updateIds.delete(id);
|
|
890
|
+
changedInstanceOps.deleteIds.add(id);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
788
893
|
}
|
|
789
894
|
/**
|
|
790
895
|
* Initializes a new ChangedInstanceIds object with information taken from a range of changesets.
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
* @note Modified element information will be taken from a range of changesets. First changeset in a range will be the 'firstChangesetId', the last will be whichever changeset the 'iModel' briefcase is currently opened on.
|
|
796
|
-
*/
|
|
797
|
-
static async initialize(accessTokenOrOpts, iModel, startChangesetId) {
|
|
798
|
-
const opts = typeof accessTokenOrOpts === "object"
|
|
799
|
-
? accessTokenOrOpts
|
|
800
|
-
: {
|
|
801
|
-
accessToken: accessTokenOrOpts,
|
|
802
|
-
iModel: iModel,
|
|
803
|
-
startChangeset: { id: startChangesetId },
|
|
804
|
-
};
|
|
805
|
-
assertHasChangeDataOptions(opts);
|
|
896
|
+
*/
|
|
897
|
+
static async initialize(opts) {
|
|
898
|
+
if ("changedInstanceIds" in opts)
|
|
899
|
+
return opts.changedInstanceIds;
|
|
806
900
|
const iModelId = opts.iModel.iModelId;
|
|
807
901
|
const accessToken = opts.accessToken;
|
|
808
|
-
const
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
902
|
+
const startChangeset = "startChangeset" in opts ? opts.startChangeset : undefined;
|
|
903
|
+
const changesetRanges = startChangeset !== undefined
|
|
904
|
+
? [
|
|
905
|
+
[
|
|
906
|
+
startChangeset.index ??
|
|
907
|
+
(await core_backend_1.IModelHost.hubAccess.queryChangeset({
|
|
813
908
|
iModelId,
|
|
814
|
-
changeset: {
|
|
909
|
+
changeset: {
|
|
910
|
+
id: startChangeset.id ?? opts.iModel.changeset.id,
|
|
911
|
+
},
|
|
815
912
|
accessToken,
|
|
816
913
|
})).index,
|
|
817
|
-
opts.iModel.changeset.index
|
|
818
|
-
|
|
914
|
+
opts.iModel.changeset.index ??
|
|
915
|
+
(await core_backend_1.IModelHost.hubAccess.queryChangeset({
|
|
819
916
|
iModelId,
|
|
820
917
|
changeset: { id: opts.iModel.changeset.id },
|
|
821
918
|
accessToken,
|
|
822
919
|
})).index,
|
|
823
|
-
]
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
changedInstanceIds
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
920
|
+
],
|
|
921
|
+
]
|
|
922
|
+
: "changesetRanges" in opts
|
|
923
|
+
? opts.changesetRanges
|
|
924
|
+
: undefined;
|
|
925
|
+
const csFileProps = changesetRanges !== undefined
|
|
926
|
+
? (await Promise.all(changesetRanges.map(async ([first, end]) => core_backend_1.IModelHost.hubAccess.downloadChangesets({
|
|
927
|
+
accessToken,
|
|
928
|
+
iModelId,
|
|
929
|
+
range: { first, end },
|
|
930
|
+
targetDir: core_backend_1.BriefcaseManager.getChangeSetsPath(iModelId),
|
|
931
|
+
})))).flat()
|
|
932
|
+
: "csFileProps" in opts
|
|
933
|
+
? opts.csFileProps
|
|
934
|
+
: undefined;
|
|
935
|
+
if (csFileProps === undefined)
|
|
936
|
+
return undefined;
|
|
937
|
+
const changedInstanceIds = new ChangedInstanceIds(opts.iModel);
|
|
938
|
+
const relationshipECClassIdsToSkip = new Set();
|
|
939
|
+
for await (const row of opts.iModel.createQueryReader("SELECT ECInstanceId FROM ECDbMeta.ECClassDef where ECInstanceId IS (BisCore.ElementDrivesElement)")) {
|
|
940
|
+
relationshipECClassIdsToSkip.add(row.ECInstanceId);
|
|
941
|
+
}
|
|
942
|
+
for (const csFile of csFileProps) {
|
|
943
|
+
const csReader = core_backend_1.SqliteChangesetReader.openFile({
|
|
944
|
+
fileName: csFile.pathname,
|
|
945
|
+
db: opts.iModel,
|
|
946
|
+
disableSchemaCheck: true,
|
|
947
|
+
});
|
|
948
|
+
const csAdaptor = new core_backend_1.ChangesetECAdaptor(csReader);
|
|
949
|
+
const ecChangeUnifier = new core_backend_1.PartialECChangeUnifier();
|
|
950
|
+
while (csAdaptor.step()) {
|
|
951
|
+
ecChangeUnifier.appendFrom(csAdaptor);
|
|
952
|
+
}
|
|
953
|
+
const changes = [...ecChangeUnifier.instances];
|
|
954
|
+
for (const change of changes) {
|
|
955
|
+
if (change.ECClassId !== undefined &&
|
|
956
|
+
relationshipECClassIdsToSkip.has(change.ECClassId))
|
|
957
|
+
continue;
|
|
958
|
+
await changedInstanceIds.addChange(change);
|
|
959
|
+
}
|
|
960
|
+
csReader.close();
|
|
961
|
+
}
|
|
844
962
|
return changedInstanceIds;
|
|
845
963
|
}
|
|
846
964
|
}
|