@itwin/imodel-transformer 2.0.0-dev.5 → 2.0.0-dev.50
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/README.md +13 -27
- package/lib/cjs/Algo.js.map +1 -1
- package/lib/cjs/BigMap.d.ts.map +1 -1
- package/lib/cjs/BigMap.js.map +1 -1
- package/lib/cjs/BranchProvenanceInitializer.d.ts.map +1 -1
- package/lib/cjs/BranchProvenanceInitializer.js +34 -36
- package/lib/cjs/BranchProvenanceInitializer.js.map +1 -1
- package/lib/cjs/ChangesetScanner.d.ts +60 -0
- package/lib/cjs/ChangesetScanner.d.ts.map +1 -0
- package/lib/cjs/ChangesetScanner.js +101 -0
- package/lib/cjs/ChangesetScanner.js.map +1 -0
- package/lib/cjs/ECReferenceTypesCache.d.ts +0 -3
- package/lib/cjs/ECReferenceTypesCache.d.ts.map +1 -1
- package/lib/cjs/ECReferenceTypesCache.js +61 -103
- package/lib/cjs/ECReferenceTypesCache.js.map +1 -1
- package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.d.ts.map +1 -1
- package/lib/cjs/ECSqlReaderAsyncIterableIteratorAdapter.js.map +1 -1
- package/lib/cjs/ElementAspectCleanup.d.ts +16 -0
- package/lib/cjs/ElementAspectCleanup.d.ts.map +1 -0
- package/lib/cjs/ElementAspectCleanup.js +83 -0
- package/lib/cjs/ElementAspectCleanup.js.map +1 -0
- package/lib/cjs/ElementAspectExportCoordinator.d.ts +44 -0
- package/lib/cjs/ElementAspectExportCoordinator.d.ts.map +1 -0
- package/lib/cjs/ElementAspectExportCoordinator.js +148 -0
- package/lib/cjs/ElementAspectExportCoordinator.js.map +1 -0
- package/lib/cjs/ElementAspectExportProcessor.d.ts +43 -0
- package/lib/cjs/ElementAspectExportProcessor.d.ts.map +1 -0
- package/lib/cjs/ElementAspectExportProcessor.js +167 -0
- package/lib/cjs/ElementAspectExportProcessor.js.map +1 -0
- package/lib/cjs/ElementCascadingDeleter.d.ts +3 -3
- package/lib/cjs/ElementCascadingDeleter.d.ts.map +1 -1
- package/lib/cjs/ElementCascadingDeleter.js +12 -12
- package/lib/cjs/ElementCascadingDeleter.js.map +1 -1
- package/lib/cjs/EntityExistenceCache.d.ts +43 -0
- package/lib/cjs/EntityExistenceCache.d.ts.map +1 -0
- package/lib/cjs/EntityExistenceCache.js +91 -0
- package/lib/cjs/EntityExistenceCache.js.map +1 -0
- package/lib/cjs/EntityMap.d.ts.map +1 -1
- package/lib/cjs/EntityMap.js.map +1 -1
- package/lib/cjs/EntityUnifier.d.ts +8 -8
- package/lib/cjs/EntityUnifier.d.ts.map +1 -1
- package/lib/cjs/EntityUnifier.js +55 -32
- package/lib/cjs/EntityUnifier.js.map +1 -1
- package/lib/cjs/IModelCloneContext.d.ts +11 -5
- package/lib/cjs/IModelCloneContext.d.ts.map +1 -1
- package/lib/cjs/IModelCloneContext.js +94 -58
- package/lib/cjs/IModelCloneContext.js.map +1 -1
- package/lib/cjs/IModelExporter.d.ts +108 -34
- package/lib/cjs/IModelExporter.d.ts.map +1 -1
- package/lib/cjs/IModelExporter.js +702 -208
- package/lib/cjs/IModelExporter.js.map +1 -1
- package/lib/cjs/IModelImporter.d.ts +50 -25
- package/lib/cjs/IModelImporter.d.ts.map +1 -1
- package/lib/cjs/IModelImporter.js +231 -130
- package/lib/cjs/IModelImporter.js.map +1 -1
- package/lib/cjs/IModelTransformContext.d.ts +54 -0
- package/lib/cjs/IModelTransformContext.d.ts.map +1 -0
- package/lib/cjs/IModelTransformContext.js +3 -0
- package/lib/cjs/IModelTransformContext.js.map +1 -0
- package/lib/cjs/IModelTransformer.d.ts +125 -203
- package/lib/cjs/IModelTransformer.d.ts.map +1 -1
- package/lib/cjs/IModelTransformer.js +646 -1190
- package/lib/cjs/IModelTransformer.js.map +1 -1
- package/lib/cjs/IModelTransformerError.d.ts +82 -0
- package/lib/cjs/IModelTransformerError.d.ts.map +1 -0
- package/lib/cjs/IModelTransformerError.js +91 -0
- package/lib/cjs/IModelTransformerError.js.map +1 -0
- package/lib/cjs/ProvenanceManager.d.ts +182 -0
- package/lib/cjs/ProvenanceManager.d.ts.map +1 -0
- package/lib/cjs/ProvenanceManager.js +743 -0
- package/lib/cjs/ProvenanceManager.js.map +1 -0
- package/lib/cjs/SyncTypeResolver.d.ts +34 -0
- package/lib/cjs/SyncTypeResolver.d.ts.map +1 -0
- package/lib/cjs/SyncTypeResolver.js +98 -0
- package/lib/cjs/SyncTypeResolver.js.map +1 -0
- package/lib/cjs/TransformerLoggerCategory.d.ts +1 -1
- package/lib/cjs/TransformerLoggerCategory.js +1 -1
- package/lib/cjs/TransformerLoggerCategory.js.map +1 -1
- package/lib/cjs/TransformerPackageMetadata.d.ts +8 -0
- package/lib/cjs/TransformerPackageMetadata.d.ts.map +1 -0
- package/lib/cjs/TransformerPackageMetadata.js +47 -0
- package/lib/cjs/TransformerPackageMetadata.js.map +1 -0
- package/lib/cjs/imodel-transformer.d.ts +19 -0
- package/lib/cjs/imodel-transformer.d.ts.map +1 -1
- package/lib/cjs/imodel-transformer.js +53 -34
- package/lib/cjs/imodel-transformer.js.map +1 -1
- package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.d.ts +29 -0
- package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.d.ts.map +1 -0
- package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.js +212 -0
- package/lib/cjs/schema-processing/DynamicSchemaUnionStrategy.js.map +1 -0
- package/lib/cjs/schema-processing/SchemaProcessingCoordinator.d.ts +25 -0
- package/lib/cjs/schema-processing/SchemaProcessingCoordinator.d.ts.map +1 -0
- package/lib/cjs/schema-processing/SchemaProcessingCoordinator.js +196 -0
- package/lib/cjs/schema-processing/SchemaProcessingCoordinator.js.map +1 -0
- package/lib/cjs/schema-processing/SchemaProcessingStrategy.d.ts +59 -0
- package/lib/cjs/schema-processing/SchemaProcessingStrategy.d.ts.map +1 -0
- package/lib/cjs/schema-processing/SchemaProcessingStrategy.js +28 -0
- package/lib/cjs/schema-processing/SchemaProcessingStrategy.js.map +1 -0
- package/lib/cjs/schema-processing.d.ts +7 -0
- package/lib/cjs/schema-processing.d.ts.map +1 -0
- package/lib/cjs/schema-processing.js +27 -0
- package/lib/cjs/schema-processing.js.map +1 -0
- package/package.json +65 -43
- package/lib/cjs/DetachedExportElementAspectsStrategy.d.ts +0 -16
- package/lib/cjs/DetachedExportElementAspectsStrategy.d.ts.map +0 -1
- package/lib/cjs/DetachedExportElementAspectsStrategy.js +0 -106
- package/lib/cjs/DetachedExportElementAspectsStrategy.js.map +0 -1
- package/lib/cjs/ExportElementAspectsStrategy.d.ts +0 -35
- package/lib/cjs/ExportElementAspectsStrategy.d.ts.map +0 -1
- package/lib/cjs/ExportElementAspectsStrategy.js +0 -52
- package/lib/cjs/ExportElementAspectsStrategy.js.map +0 -1
- package/lib/cjs/ExportElementAspectsWithElementsStrategy.d.ts +0 -12
- package/lib/cjs/ExportElementAspectsWithElementsStrategy.d.ts.map +0 -1
- package/lib/cjs/ExportElementAspectsWithElementsStrategy.js +0 -47
- package/lib/cjs/ExportElementAspectsWithElementsStrategy.js.map +0 -1
|
@@ -13,8 +13,11 @@ const core_bentley_1 = require("@itwin/core-bentley");
|
|
|
13
13
|
const core_common_1 = require("@itwin/core-common");
|
|
14
14
|
const TransformerLoggerCategory_1 = require("./TransformerLoggerCategory");
|
|
15
15
|
const core_backend_1 = require("@itwin/core-backend");
|
|
16
|
-
const
|
|
16
|
+
const node_assert_1 = require("node:assert");
|
|
17
17
|
const ElementCascadingDeleter_1 = require("./ElementCascadingDeleter");
|
|
18
|
+
const ElementAspectCleanup_1 = require("./ElementAspectCleanup");
|
|
19
|
+
const ecschema_metadata_1 = require("@itwin/ecschema-metadata");
|
|
20
|
+
const IModelTransformerError_1 = require("./IModelTransformerError");
|
|
18
21
|
const loggerCategory = TransformerLoggerCategory_1.TransformerLoggerCategory.IModelImporter;
|
|
19
22
|
/** Base class for importing data into an iModel.
|
|
20
23
|
* @see [iModel Transformation and Data Exchange]($docs/learning/transformer/index.md)
|
|
@@ -25,6 +28,23 @@ const loggerCategory = TransformerLoggerCategory_1.TransformerLoggerCategory.IMo
|
|
|
25
28
|
class IModelImporter {
|
|
26
29
|
/** The read/write target iModel. */
|
|
27
30
|
targetDb;
|
|
31
|
+
/** The [[EditTxn]] used for write operations on the target iModel.
|
|
32
|
+
* @beta
|
|
33
|
+
*/
|
|
34
|
+
_editTxn;
|
|
35
|
+
/** The [[EditTxn]] used for write operations on the target iModel.
|
|
36
|
+
* @beta
|
|
37
|
+
*/
|
|
38
|
+
get editTxn() {
|
|
39
|
+
return this._editTxn;
|
|
40
|
+
}
|
|
41
|
+
_elementAspectCleanup;
|
|
42
|
+
/** Deletes replaceable ElementAspects through this importer's customized deletion callback.
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
get elementAspectCleanup() {
|
|
46
|
+
return this._elementAspectCleanup;
|
|
47
|
+
}
|
|
28
48
|
/** resolved initialization options for the importer
|
|
29
49
|
* @beta
|
|
30
50
|
*/
|
|
@@ -38,6 +58,7 @@ class IModelImporter {
|
|
|
38
58
|
* To resolve code values to their intended values call [[IModelImporter.resolveDuplicateCodeValues]].
|
|
39
59
|
*/
|
|
40
60
|
_duplicateCodeValueMap;
|
|
61
|
+
_entityExistenceCaches = new Set();
|
|
41
62
|
/**
|
|
42
63
|
* A set of elementIds that the transformer adds to while exporting elements to indicate that the element already exists in the target.
|
|
43
64
|
* Defaults to an empty set.
|
|
@@ -71,11 +92,12 @@ class IModelImporter {
|
|
|
71
92
|
"geometryGuid", // cannot compare GeometricModel.GeometryGuid values across iModels
|
|
72
93
|
]);
|
|
73
94
|
/** Construct a new IModelImporter
|
|
74
|
-
* @param
|
|
95
|
+
* @param editTxn The [[EditTxn]] to use for write operations on the target iModel. The target db is derived from `editTxn.iModel`.
|
|
75
96
|
* @param options The options that specify how the import should be done.
|
|
76
97
|
*/
|
|
77
|
-
constructor(
|
|
78
|
-
this.targetDb =
|
|
98
|
+
constructor(editTxn, options) {
|
|
99
|
+
this.targetDb = editTxn.iModel;
|
|
100
|
+
this._editTxn = editTxn;
|
|
79
101
|
this.options = {
|
|
80
102
|
autoExtendProjectExtents: options?.autoExtendProjectExtents ?? true,
|
|
81
103
|
preserveElementIdsForFiltering: options?.preserveElementIdsForFiltering ?? false,
|
|
@@ -83,6 +105,19 @@ class IModelImporter {
|
|
|
83
105
|
skipPropagateChangesToRootElements: options?.skipPropagateChangesToRootElements ?? true,
|
|
84
106
|
};
|
|
85
107
|
this._duplicateCodeValueMap = new Map();
|
|
108
|
+
this._elementAspectCleanup = new ElementAspectCleanup_1.ElementAspectCleanup(this.targetDb, this._editTxn, async (aspect) => this.onDeleteElementAspect(aspect));
|
|
109
|
+
}
|
|
110
|
+
/** Register a transformation-scoped existence cache for delete invalidation.
|
|
111
|
+
* @internal
|
|
112
|
+
*/
|
|
113
|
+
registerEntityExistenceCache(cache) {
|
|
114
|
+
this._entityExistenceCaches.add(cache);
|
|
115
|
+
}
|
|
116
|
+
/** Stop invalidating a transformation-scoped existence cache.
|
|
117
|
+
* @internal
|
|
118
|
+
*/
|
|
119
|
+
unregisterEntityExistenceCache(cache) {
|
|
120
|
+
this._entityExistenceCaches.delete(cache);
|
|
86
121
|
}
|
|
87
122
|
/**
|
|
88
123
|
* Checks [[IModelImportOptions.skipPropagateChangesToRootElements]], [[IModelImporter.rootElementIds]], and [[IModelImporter.doNotUpdateElementIds]] and returns true for 'do not update', false for do 'update'.
|
|
@@ -105,9 +140,15 @@ class IModelImporter {
|
|
|
105
140
|
this._elementsToUpdateDuringPreserveIds.add(elementId);
|
|
106
141
|
}
|
|
107
142
|
/** Import the specified ModelProps (either as an insert or an update) into the target iModel. */
|
|
108
|
-
importModel(modelProps) {
|
|
143
|
+
async importModel(modelProps) {
|
|
109
144
|
if (undefined === modelProps.id || !core_bentley_1.Id64.isValidId64(modelProps.id))
|
|
110
|
-
|
|
145
|
+
core_bentley_1.ITwinError.throwError({
|
|
146
|
+
iTwinErrorId: {
|
|
147
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
148
|
+
key: IModelTransformerError_1.IModelTransformerError.InvalidModelId,
|
|
149
|
+
},
|
|
150
|
+
message: "Model Id not provided, should be the same as the ModeledElementId",
|
|
151
|
+
});
|
|
111
152
|
if (this.doNotUpdateElement(modelProps.id)) {
|
|
112
153
|
core_bentley_1.Logger.logInfo(loggerCategory, `Do not update target model ${modelProps.id}`);
|
|
113
154
|
return;
|
|
@@ -115,14 +156,14 @@ class IModelImporter {
|
|
|
115
156
|
try {
|
|
116
157
|
const model = this.targetDb.models.getModel(modelProps.id); // throws IModelError.NotFound if model does not exist
|
|
117
158
|
if (hasEntityChanged(model, modelProps, this._modelPropertiesToIgnore)) {
|
|
118
|
-
this.onUpdateModel(modelProps);
|
|
159
|
+
await this.onUpdateModel(modelProps);
|
|
119
160
|
}
|
|
120
161
|
}
|
|
121
162
|
catch (error) {
|
|
122
163
|
// catch NotFound error and insertModel
|
|
123
164
|
if (error instanceof core_common_1.IModelError &&
|
|
124
165
|
error.errorNumber === core_bentley_1.IModelStatus.NotFound) {
|
|
125
|
-
this.onInsertModel(modelProps);
|
|
166
|
+
await this.onInsertModel(modelProps);
|
|
126
167
|
return;
|
|
127
168
|
}
|
|
128
169
|
throw error;
|
|
@@ -131,29 +172,35 @@ class IModelImporter {
|
|
|
131
172
|
/** Create a new Model from the specified ModelProps and insert it into the target iModel.
|
|
132
173
|
* @note A subclass may override this method to customize insert behavior but should call `super.onInsertModel`.
|
|
133
174
|
*/
|
|
134
|
-
onInsertModel(modelProps) {
|
|
175
|
+
async onInsertModel(modelProps) {
|
|
135
176
|
try {
|
|
136
|
-
const modelId = this.
|
|
177
|
+
const modelId = this._editTxn.insertModel(modelProps);
|
|
137
178
|
core_bentley_1.Logger.logInfo(loggerCategory, `Inserted ${this.formatModelForLogger(modelProps)}`);
|
|
138
|
-
this.trackProgress();
|
|
179
|
+
await this.trackProgress();
|
|
139
180
|
return modelId;
|
|
140
181
|
}
|
|
141
182
|
catch (error) {
|
|
142
183
|
if (!this.targetDb.containsClass(modelProps.classFullName)) {
|
|
143
|
-
//
|
|
144
|
-
|
|
145
|
-
|
|
184
|
+
// Translate only confirmed missing-class failures; otherwise retain the backend error's identity.
|
|
185
|
+
core_bentley_1.ITwinError.throwError({
|
|
186
|
+
iTwinErrorId: {
|
|
187
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
188
|
+
key: IModelTransformerError_1.IModelTransformerError.TargetClassNotFound,
|
|
189
|
+
},
|
|
190
|
+
message: `Model class "${modelProps.classFullName}" not found in the target iModel. Was the latest version of the schema imported?`,
|
|
191
|
+
cause: error,
|
|
192
|
+
});
|
|
146
193
|
}
|
|
147
|
-
throw error;
|
|
194
|
+
throw error;
|
|
148
195
|
}
|
|
149
196
|
}
|
|
150
197
|
/** Update an existing Model in the target iModel from the specified ModelProps.
|
|
151
198
|
* @note A subclass may override this method to customize update behavior but should call `super.onUpdateModel`.
|
|
152
199
|
*/
|
|
153
|
-
onUpdateModel(modelProps) {
|
|
154
|
-
this.
|
|
200
|
+
async onUpdateModel(modelProps) {
|
|
201
|
+
this._editTxn.updateModel(modelProps);
|
|
155
202
|
core_bentley_1.Logger.logInfo(loggerCategory, `Updated ${this.formatModelForLogger(modelProps)}`);
|
|
156
|
-
this.trackProgress();
|
|
203
|
+
await this.trackProgress();
|
|
157
204
|
}
|
|
158
205
|
/** Format a Model for the Logger. */
|
|
159
206
|
formatModelForLogger(modelProps) {
|
|
@@ -164,18 +211,18 @@ class IModelImporter {
|
|
|
164
211
|
* Tries to update an element with the specified element properties.
|
|
165
212
|
* If a duplicate code error occurs, it assigns a new unique code value and retries the update
|
|
166
213
|
*/
|
|
167
|
-
tryUpdateElement(elemProps) {
|
|
214
|
+
async tryUpdateElement(elemProps) {
|
|
168
215
|
try {
|
|
169
|
-
this.onUpdateElement(elemProps);
|
|
216
|
+
await this.onUpdateElement(elemProps);
|
|
170
217
|
}
|
|
171
218
|
catch (err) {
|
|
172
219
|
if (err.errorNumber === core_bentley_1.IModelStatus.DuplicateCode) {
|
|
173
|
-
|
|
220
|
+
(0, node_assert_1.strict)(elemProps.code.value !== undefined, "NULL code values are always considered unique and cannot clash");
|
|
174
221
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
175
222
|
this._duplicateCodeValueMap.set(elemProps.id, elemProps.code.value);
|
|
176
223
|
// Using NULL code values as an alternative is not valid because definition elements cannot have NULL code values.
|
|
177
224
|
elemProps.code.value = core_bentley_1.Guid.createValue();
|
|
178
|
-
this.onUpdateElement(elemProps);
|
|
225
|
+
await this.onUpdateElement(elemProps);
|
|
179
226
|
}
|
|
180
227
|
else {
|
|
181
228
|
throw err;
|
|
@@ -183,7 +230,7 @@ class IModelImporter {
|
|
|
183
230
|
}
|
|
184
231
|
}
|
|
185
232
|
/** Import the specified ElementProps (either as an insert or an update) into the target iModel. */
|
|
186
|
-
importElement(elementProps) {
|
|
233
|
+
async importElement(elementProps) {
|
|
187
234
|
if (undefined !== elementProps.id &&
|
|
188
235
|
this.doNotUpdateElement(elementProps.id)) {
|
|
189
236
|
core_bentley_1.Logger.logInfo(loggerCategory, `Do not update target element ${elementProps.id}`);
|
|
@@ -191,7 +238,13 @@ class IModelImporter {
|
|
|
191
238
|
}
|
|
192
239
|
if (this.options.preserveElementIdsForFiltering) {
|
|
193
240
|
if (elementProps.id === undefined) {
|
|
194
|
-
|
|
241
|
+
core_bentley_1.ITwinError.throwError({
|
|
242
|
+
iTwinErrorId: {
|
|
243
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
244
|
+
key: IModelTransformerError_1.IModelTransformerError.ElementIdRequired,
|
|
245
|
+
},
|
|
246
|
+
message: "elementProps.id must be defined during a preserveIds operation",
|
|
247
|
+
});
|
|
195
248
|
}
|
|
196
249
|
// Categories are the only element that onInserted will immediately insert a new element (their default subcategory)
|
|
197
250
|
// since default subcategories always exist and always will be inserted after their categories, we treat them as an update
|
|
@@ -199,24 +252,24 @@ class IModelImporter {
|
|
|
199
252
|
// Always present elements (0xe, 0x1, 0x10) also will be updated to prevent duplicate inserts.
|
|
200
253
|
if ((isSubCategory(elementProps) && isDefaultSubCategory(elementProps)) ||
|
|
201
254
|
this._rootElementIds.has(elementProps.id)) {
|
|
202
|
-
this.onUpdateElement(elementProps);
|
|
255
|
+
await this.onUpdateElement(elementProps);
|
|
203
256
|
}
|
|
204
257
|
else {
|
|
205
258
|
if (this._elementsToUpdateDuringPreserveIds.has(elementProps.id)) {
|
|
206
|
-
this.tryUpdateElement(elementProps);
|
|
259
|
+
await this.tryUpdateElement(elementProps);
|
|
207
260
|
this._elementsToUpdateDuringPreserveIds.delete(elementProps.id);
|
|
208
261
|
}
|
|
209
262
|
else {
|
|
210
|
-
this.onInsertElement(elementProps);
|
|
263
|
+
await this.onInsertElement(elementProps);
|
|
211
264
|
}
|
|
212
265
|
}
|
|
213
266
|
}
|
|
214
267
|
else {
|
|
215
268
|
if (undefined !== elementProps.id) {
|
|
216
|
-
this.tryUpdateElement(elementProps);
|
|
269
|
+
await this.tryUpdateElement(elementProps);
|
|
217
270
|
}
|
|
218
271
|
else {
|
|
219
|
-
elementProps.id = this.onInsertElement(elementProps); // targetElementProps.id assigned by insertElement
|
|
272
|
+
elementProps.id = await this.onInsertElement(elementProps); // targetElementProps.id assigned by insertElement
|
|
220
273
|
}
|
|
221
274
|
}
|
|
222
275
|
return elementProps.id;
|
|
@@ -225,16 +278,15 @@ class IModelImporter {
|
|
|
225
278
|
* @returns The Id of the newly inserted Element.
|
|
226
279
|
* @note A subclass may override this method to customize insert behavior but should call `super.onInsertElement`.
|
|
227
280
|
*/
|
|
228
|
-
onInsertElement(elementProps) {
|
|
229
|
-
/* eslint-disable @typescript-eslint/no-deprecated */
|
|
281
|
+
async onInsertElement(elementProps) {
|
|
230
282
|
try {
|
|
231
|
-
const elementId = this.
|
|
283
|
+
const elementId = this._editTxn.insertElement(elementProps, {
|
|
232
284
|
forceUseId: this.options.preserveElementIdsForFiltering,
|
|
233
285
|
});
|
|
234
286
|
// set the id like [IModelDb.insertElement]($backend), does, the raw nativeDb method does not
|
|
235
287
|
elementProps.id = elementId;
|
|
236
288
|
core_bentley_1.Logger.logInfo(loggerCategory, `Inserted ${this.formatElementForLogger(elementProps)}`);
|
|
237
|
-
this.trackProgress();
|
|
289
|
+
await this.trackProgress();
|
|
238
290
|
if (this.options.simplifyElementGeometry) {
|
|
239
291
|
this.targetDb.simplifyElementGeometry({
|
|
240
292
|
id: elementId,
|
|
@@ -246,26 +298,35 @@ class IModelImporter {
|
|
|
246
298
|
}
|
|
247
299
|
catch (error) {
|
|
248
300
|
if (!this.targetDb.containsClass(elementProps.classFullName)) {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
301
|
+
core_bentley_1.ITwinError.throwError({
|
|
302
|
+
iTwinErrorId: {
|
|
303
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
304
|
+
key: IModelTransformerError_1.IModelTransformerError.TargetClassNotFound,
|
|
305
|
+
},
|
|
306
|
+
message: `Element class "${elementProps.classFullName}" not found in the target iModel. Was the latest version of the schema imported?`,
|
|
307
|
+
cause: error,
|
|
308
|
+
});
|
|
252
309
|
}
|
|
253
|
-
throw error;
|
|
310
|
+
throw error;
|
|
254
311
|
}
|
|
255
|
-
/* eslint-enable @typescript-eslint/no-deprecated */
|
|
256
312
|
}
|
|
257
313
|
/** Update an existing Element in the target iModel from the specified ElementProps.
|
|
258
314
|
* @note A subclass may override this method to customize update behavior but should call `super.onUpdateElement`.
|
|
259
315
|
*/
|
|
260
|
-
onUpdateElement(elementProps) {
|
|
316
|
+
async onUpdateElement(elementProps) {
|
|
261
317
|
if (!elementProps.id) {
|
|
262
|
-
|
|
318
|
+
core_bentley_1.ITwinError.throwError({
|
|
319
|
+
iTwinErrorId: {
|
|
320
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
321
|
+
key: IModelTransformerError_1.IModelTransformerError.ElementIdRequired,
|
|
322
|
+
},
|
|
323
|
+
message: "ElementId not provided",
|
|
324
|
+
});
|
|
263
325
|
}
|
|
264
|
-
this.
|
|
326
|
+
this._editTxn.updateElement(elementProps);
|
|
265
327
|
core_bentley_1.Logger.logInfo(loggerCategory, `Updated ${this.formatElementForLogger(elementProps)}`);
|
|
266
|
-
this.trackProgress();
|
|
328
|
+
await this.trackProgress();
|
|
267
329
|
if (this.options.simplifyElementGeometry) {
|
|
268
|
-
/* eslint-disable-next-line @typescript-eslint/no-deprecated */
|
|
269
330
|
this.targetDb.simplifyElementGeometry({
|
|
270
331
|
id: elementProps.id,
|
|
271
332
|
convertBReps: true,
|
|
@@ -277,30 +338,36 @@ class IModelImporter {
|
|
|
277
338
|
* Will delete special elements like definition elements and subjects.
|
|
278
339
|
* @note A subclass may override this method to customize delete behavior but should call `super.onDeleteElement`.
|
|
279
340
|
*/
|
|
280
|
-
onDeleteElement(elementId) {
|
|
281
|
-
(0, ElementCascadingDeleter_1.deleteElementTreeCascade)(this.
|
|
341
|
+
async onDeleteElement(elementId) {
|
|
342
|
+
(0, ElementCascadingDeleter_1.deleteElementTreeCascade)(this._editTxn, elementId);
|
|
282
343
|
core_bentley_1.Logger.logInfo(loggerCategory, `Deleted element ${elementId} and its descendants`);
|
|
283
|
-
this.trackProgress();
|
|
344
|
+
await this.trackProgress();
|
|
284
345
|
}
|
|
285
346
|
/** Delete the specified Element from the target iModel. */
|
|
286
|
-
deleteElement(elementId) {
|
|
347
|
+
async deleteElement(elementId) {
|
|
287
348
|
if (this.doNotUpdateElement(elementId)) {
|
|
288
349
|
core_bentley_1.Logger.logInfo(loggerCategory, `Do not delete target element ${elementId}`);
|
|
289
350
|
return;
|
|
290
351
|
}
|
|
291
|
-
this.onDeleteElement(elementId);
|
|
352
|
+
await this.onDeleteElement(elementId);
|
|
353
|
+
// Element deletion cascades can remove descendants and their submodels.
|
|
354
|
+
for (const cache of this._entityExistenceCaches)
|
|
355
|
+
cache.clearDb(this.targetDb);
|
|
292
356
|
}
|
|
293
357
|
/** Delete the specified Model from the target iModel.
|
|
294
358
|
* @note A subclass may override this method to customize delete behavior but should call `super.onDeleteModel`.
|
|
295
359
|
*/
|
|
296
|
-
onDeleteModel(modelId) {
|
|
297
|
-
this.
|
|
360
|
+
async onDeleteModel(modelId) {
|
|
361
|
+
this._editTxn.deleteModel(modelId);
|
|
298
362
|
core_bentley_1.Logger.logInfo(loggerCategory, `Deleted model ${modelId}`);
|
|
299
|
-
this.trackProgress();
|
|
363
|
+
await this.trackProgress();
|
|
300
364
|
}
|
|
301
365
|
/** Delete the specified Model from the target iModel. */
|
|
302
|
-
deleteModel(modelId) {
|
|
303
|
-
this.onDeleteModel(modelId);
|
|
366
|
+
async deleteModel(modelId) {
|
|
367
|
+
await this.onDeleteModel(modelId);
|
|
368
|
+
const modelReference = core_backend_1.EntityReferences.fromEntityType(modelId, core_common_1.ConcreteEntityTypes.Model);
|
|
369
|
+
for (const cache of this._entityExistenceCaches)
|
|
370
|
+
cache.invalidate(this.targetDb, modelReference);
|
|
304
371
|
}
|
|
305
372
|
/** Format an Element for the Logger. */
|
|
306
373
|
formatElementForLogger(elementProps) {
|
|
@@ -312,14 +379,14 @@ class IModelImporter {
|
|
|
312
379
|
return `${elementProps.classFullName} ${namePiece}[${elementProps.id}]`;
|
|
313
380
|
}
|
|
314
381
|
/** Import an ElementUniqueAspect into the target iModel. */
|
|
315
|
-
importElementUniqueAspect(aspectProps) {
|
|
382
|
+
async importElementUniqueAspect(aspectProps) {
|
|
316
383
|
const aspects = this.targetDb.elements.getAspects(aspectProps.element.id, aspectProps.classFullName);
|
|
317
384
|
if (aspects.length === 0) {
|
|
318
385
|
return this.onInsertElementAspect(aspectProps);
|
|
319
386
|
}
|
|
320
387
|
else if (hasEntityChanged(aspects[0], aspectProps)) {
|
|
321
388
|
aspectProps.id = aspects[0].id;
|
|
322
|
-
this.onUpdateElementAspect(aspectProps);
|
|
389
|
+
await this.onUpdateElementAspect(aspectProps);
|
|
323
390
|
}
|
|
324
391
|
return aspects[0].id;
|
|
325
392
|
}
|
|
@@ -329,7 +396,7 @@ class IModelImporter {
|
|
|
329
396
|
* @note For insert vs. update reasons, it is important to process all ElementMultiAspects owned by an Element at once since we don't have aspect-specific provenance.
|
|
330
397
|
* @returns the array of ids of the resulting ElementMultiAspects, in the same order of the aspectPropsArray parameter
|
|
331
398
|
*/
|
|
332
|
-
importElementMultiAspects(aspectPropsArray,
|
|
399
|
+
async importElementMultiAspects(aspectPropsArray,
|
|
333
400
|
/** caller must use this to enforce any aspects added by IModelTransformer are not considered for update */
|
|
334
401
|
filterFunc = () => true) {
|
|
335
402
|
const result = new Array(aspectPropsArray.length).fill(undefined);
|
|
@@ -337,91 +404,96 @@ class IModelImporter {
|
|
|
337
404
|
return result;
|
|
338
405
|
}
|
|
339
406
|
const elementId = aspectPropsArray[0].element.id;
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
407
|
+
const proposedAspectsByClass = new Map();
|
|
408
|
+
aspectPropsArray.forEach((props, index) => {
|
|
409
|
+
const proposedAspects = proposedAspectsByClass.get(props.classFullName) ?? [];
|
|
410
|
+
proposedAspects.push({ props, index });
|
|
411
|
+
proposedAspectsByClass.set(props.classFullName, proposedAspects);
|
|
344
412
|
});
|
|
345
413
|
// Handle ElementMultiAspects in groups by class
|
|
346
|
-
|
|
347
|
-
const proposedAspects = aspectPropsArray
|
|
348
|
-
.map((props, index) => ({ props, index }))
|
|
349
|
-
.filter(({ props }) => aspectClassFullName === props.classFullName);
|
|
414
|
+
for (const [aspectClassFullName, proposedAspects,] of proposedAspectsByClass) {
|
|
350
415
|
const currentAspects = this.targetDb.elements
|
|
351
416
|
.getAspects(elementId, aspectClassFullName)
|
|
352
417
|
.map((props, index) => ({ props, index }))
|
|
353
418
|
.filter(({ props }) => filterFunc(props));
|
|
354
419
|
if (proposedAspects.length >= currentAspects.length) {
|
|
355
|
-
|
|
420
|
+
for (let index = 0; index < proposedAspects.length; index++) {
|
|
421
|
+
const { props, index: resultIndex } = proposedAspects[index];
|
|
356
422
|
let id;
|
|
357
423
|
if (index < currentAspects.length) {
|
|
358
424
|
id = currentAspects[index].props.id;
|
|
359
425
|
props.id = id;
|
|
360
426
|
if (hasEntityChanged(currentAspects[index].props, props)) {
|
|
361
|
-
this.onUpdateElementAspect(props);
|
|
427
|
+
await this.onUpdateElementAspect(props);
|
|
362
428
|
}
|
|
363
429
|
id = props.id;
|
|
364
430
|
}
|
|
365
431
|
else {
|
|
366
|
-
id = this.onInsertElementAspect(props);
|
|
432
|
+
id = await this.onInsertElementAspect(props);
|
|
367
433
|
}
|
|
368
434
|
result[resultIndex] = id;
|
|
369
|
-
}
|
|
435
|
+
}
|
|
370
436
|
}
|
|
371
437
|
else {
|
|
372
|
-
|
|
373
|
-
|
|
438
|
+
for (let index = 0; index < currentAspects.length; index++) {
|
|
439
|
+
const { props } = currentAspects[index];
|
|
374
440
|
if (index < proposedAspects.length) {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
441
|
+
const { props: proposedProps, index: resultIndex } = proposedAspects[index];
|
|
442
|
+
const id = props.id;
|
|
443
|
+
proposedProps.id = id;
|
|
444
|
+
if (hasEntityChanged(props, proposedProps)) {
|
|
445
|
+
await this.onUpdateElementAspect(proposedProps);
|
|
379
446
|
}
|
|
380
447
|
result[resultIndex] = id;
|
|
381
448
|
}
|
|
382
449
|
else {
|
|
383
|
-
this.onDeleteElementAspect(props);
|
|
450
|
+
await this.onDeleteElementAspect(props);
|
|
384
451
|
}
|
|
385
|
-
}
|
|
452
|
+
}
|
|
386
453
|
}
|
|
387
|
-
}
|
|
388
|
-
|
|
454
|
+
}
|
|
455
|
+
(0, node_assert_1.strict)(result.every((r) => r !== undefined));
|
|
389
456
|
return result;
|
|
390
457
|
}
|
|
391
458
|
/** Insert the ElementAspect into the target iModel.
|
|
392
459
|
* @note A subclass may override this method to customize insert behavior but should call `super.onInsertElementAspect`.
|
|
393
460
|
*/
|
|
394
|
-
onInsertElementAspect(aspectProps) {
|
|
461
|
+
async onInsertElementAspect(aspectProps) {
|
|
395
462
|
try {
|
|
396
|
-
const id = this.
|
|
463
|
+
const id = this._editTxn.insertAspect(aspectProps);
|
|
397
464
|
core_bentley_1.Logger.logInfo(loggerCategory, `Inserted ${this.formatElementAspectForLogger(aspectProps)}`);
|
|
398
|
-
this.trackProgress();
|
|
465
|
+
await this.trackProgress();
|
|
399
466
|
return id;
|
|
400
467
|
}
|
|
401
468
|
catch (error) {
|
|
402
469
|
if (!this.targetDb.containsClass(aspectProps.classFullName)) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
470
|
+
core_bentley_1.ITwinError.throwError({
|
|
471
|
+
iTwinErrorId: {
|
|
472
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
473
|
+
key: IModelTransformerError_1.IModelTransformerError.TargetClassNotFound,
|
|
474
|
+
},
|
|
475
|
+
message: `ElementAspect class "${aspectProps.classFullName}" not found in the target iModel. Was the latest version of the schema imported?`,
|
|
476
|
+
cause: error,
|
|
477
|
+
});
|
|
406
478
|
}
|
|
407
|
-
throw error;
|
|
479
|
+
throw error;
|
|
408
480
|
}
|
|
409
481
|
}
|
|
410
482
|
/** Update the ElementAspect within the target iModel.
|
|
411
483
|
* @note A subclass may override this method to customize update behavior but should call `super.onUpdateElementAspect`.
|
|
412
484
|
*/
|
|
413
|
-
onUpdateElementAspect(aspectProps) {
|
|
414
|
-
this.
|
|
485
|
+
async onUpdateElementAspect(aspectProps) {
|
|
486
|
+
this._editTxn.updateAspect(aspectProps);
|
|
415
487
|
core_bentley_1.Logger.logInfo(loggerCategory, `Updated ${this.formatElementAspectForLogger(aspectProps)}`);
|
|
416
|
-
this.trackProgress();
|
|
488
|
+
await this.trackProgress();
|
|
417
489
|
}
|
|
418
490
|
/** Delete the specified ElementAspect from the target iModel.
|
|
419
491
|
* @note A subclass may override this method to customize delete behavior but should call `super.onDeleteElementAspect`.
|
|
420
492
|
*/
|
|
421
|
-
onDeleteElementAspect(targetElementAspect) {
|
|
422
|
-
this.
|
|
493
|
+
async onDeleteElementAspect(targetElementAspect) {
|
|
494
|
+
this._editTxn.deleteAspect(targetElementAspect.id);
|
|
423
495
|
core_bentley_1.Logger.logInfo(loggerCategory, `Deleted ${this.formatElementAspectForLogger(targetElementAspect)}`);
|
|
424
|
-
this.trackProgress();
|
|
496
|
+
await this.trackProgress();
|
|
425
497
|
}
|
|
426
498
|
/** Format an ElementAspect for the Logger. */
|
|
427
499
|
formatElementAspectForLogger(elementAspectProps) {
|
|
@@ -430,7 +502,7 @@ class IModelImporter {
|
|
|
430
502
|
/** Import the specified RelationshipProps (either as an insert or an update) into the target iModel.
|
|
431
503
|
* @returns The instance Id of the inserted or updated Relationship.
|
|
432
504
|
*/
|
|
433
|
-
importRelationship(relationshipProps) {
|
|
505
|
+
async importRelationship(relationshipProps) {
|
|
434
506
|
if (undefined === relationshipProps.sourceId ||
|
|
435
507
|
!core_bentley_1.Id64.isValidId64(relationshipProps.sourceId)) {
|
|
436
508
|
core_bentley_1.Logger.logInfo(loggerCategory, `Ignoring ${relationshipProps.classFullName} instance because of invalid RelationshipProps.sourceId`);
|
|
@@ -451,7 +523,7 @@ class IModelImporter {
|
|
|
451
523
|
// if relationship found, update it
|
|
452
524
|
relationshipProps.id = relationship.id;
|
|
453
525
|
if (hasEntityChanged(relationship, relationshipProps)) {
|
|
454
|
-
this.onUpdateRelationship(relationshipProps);
|
|
526
|
+
await this.onUpdateRelationship(relationshipProps);
|
|
455
527
|
}
|
|
456
528
|
return relationshipProps.id;
|
|
457
529
|
}
|
|
@@ -463,62 +535,73 @@ class IModelImporter {
|
|
|
463
535
|
* @returns The instance Id of the newly inserted relationship.
|
|
464
536
|
* @note A subclass may override this method to customize insert behavior but should call `super.onInsertRelationship`.
|
|
465
537
|
*/
|
|
466
|
-
onInsertRelationship(relationshipProps) {
|
|
538
|
+
async onInsertRelationship(relationshipProps) {
|
|
467
539
|
try {
|
|
468
|
-
const targetRelInstanceId = this.
|
|
540
|
+
const targetRelInstanceId = this._editTxn.insertRelationship(relationshipProps);
|
|
469
541
|
core_bentley_1.Logger.logInfo(loggerCategory, `Inserted ${this.formatRelationshipForLogger(relationshipProps)}`);
|
|
470
|
-
this.trackProgress();
|
|
542
|
+
await this.trackProgress();
|
|
471
543
|
return targetRelInstanceId;
|
|
472
544
|
}
|
|
473
545
|
catch (error) {
|
|
474
546
|
if (!this.targetDb.containsClass(relationshipProps.classFullName)) {
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
547
|
+
core_bentley_1.ITwinError.throwError({
|
|
548
|
+
iTwinErrorId: {
|
|
549
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
550
|
+
key: IModelTransformerError_1.IModelTransformerError.TargetClassNotFound,
|
|
551
|
+
},
|
|
552
|
+
message: `Relationship class "${relationshipProps.classFullName}" not found in the target iModel. Was the latest version of the schema imported?`,
|
|
553
|
+
cause: error,
|
|
554
|
+
});
|
|
478
555
|
}
|
|
479
|
-
throw error;
|
|
556
|
+
throw error;
|
|
480
557
|
}
|
|
481
558
|
}
|
|
482
559
|
/** Update an existing Relationship in the target iModel from the specified RelationshipProps.
|
|
483
560
|
* @note A subclass may override this method to customize update behavior but should call `super.onUpdateRelationship`.
|
|
484
561
|
*/
|
|
485
|
-
onUpdateRelationship(relationshipProps) {
|
|
562
|
+
async onUpdateRelationship(relationshipProps) {
|
|
486
563
|
if (!relationshipProps.id) {
|
|
487
|
-
|
|
564
|
+
core_bentley_1.ITwinError.throwError({
|
|
565
|
+
iTwinErrorId: {
|
|
566
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
567
|
+
key: IModelTransformerError_1.IModelTransformerError.RelationshipIdRequired,
|
|
568
|
+
},
|
|
569
|
+
message: "Relationship instance Id not provided",
|
|
570
|
+
});
|
|
488
571
|
}
|
|
489
|
-
this.
|
|
572
|
+
this._editTxn.updateRelationship(relationshipProps);
|
|
490
573
|
core_bentley_1.Logger.logInfo(loggerCategory, `Updated ${this.formatRelationshipForLogger(relationshipProps)}`);
|
|
491
|
-
this.trackProgress();
|
|
574
|
+
await this.trackProgress();
|
|
492
575
|
}
|
|
493
576
|
/** Delete the specified Relationship from the target iModel. */
|
|
494
|
-
onDeleteRelationship(relationshipProps) {
|
|
577
|
+
async onDeleteRelationship(relationshipProps) {
|
|
495
578
|
// Only passing in what deleteInstance actually uses, full relationshipProps is not necessary.
|
|
496
|
-
this.
|
|
579
|
+
this._editTxn.deleteRelationship({
|
|
497
580
|
id: relationshipProps.id,
|
|
498
581
|
classFullName: relationshipProps.classFullName,
|
|
499
582
|
});
|
|
500
583
|
core_bentley_1.Logger.logInfo(loggerCategory, `Deleted relationship ${relationshipProps.classFullName} id=${relationshipProps.id}`);
|
|
501
|
-
this.trackProgress();
|
|
584
|
+
await this.trackProgress();
|
|
502
585
|
}
|
|
503
586
|
/** Delete the specified Relationship from the target iModel. */
|
|
504
|
-
deleteRelationship(relationshipProps) {
|
|
505
|
-
this.onDeleteRelationship(relationshipProps);
|
|
587
|
+
async deleteRelationship(relationshipProps) {
|
|
588
|
+
await this.onDeleteRelationship(relationshipProps);
|
|
506
589
|
}
|
|
507
590
|
/** Format a Relationship for the Logger. */
|
|
508
591
|
formatRelationshipForLogger(relProps) {
|
|
509
592
|
return `${relProps.classFullName} sourceId=[${relProps.sourceId}] targetId=[${relProps.targetId}]`;
|
|
510
593
|
}
|
|
511
594
|
/** Tracks incremental progress */
|
|
512
|
-
trackProgress() {
|
|
595
|
+
async trackProgress() {
|
|
513
596
|
this._progressCounter++;
|
|
514
597
|
if (0 === this._progressCounter % this.progressInterval) {
|
|
515
|
-
this.onProgress();
|
|
598
|
+
await this.onProgress();
|
|
516
599
|
}
|
|
517
600
|
}
|
|
518
601
|
/** This method is called when IModelImporter has made incremental progress based on the [[progressInterval]] setting.
|
|
519
602
|
* @note A subclass may override this method to report custom progress but should call `super.onProgress`.
|
|
520
603
|
*/
|
|
521
|
-
onProgress() { }
|
|
604
|
+
async onProgress() { }
|
|
522
605
|
/** Optionally compute the projectExtents for the target iModel depending on the options for this IModelImporter.
|
|
523
606
|
* @note This method is automatically called from [IModelTransformer.process]($transformer).
|
|
524
607
|
* @see [IModelDb.computeProjectExtents]($backend), [[autoExtendProjectExtents]]
|
|
@@ -535,13 +618,15 @@ class IModelImporter {
|
|
|
535
618
|
const excludeOutliers = typeof this.options.autoExtendProjectExtents === "object"
|
|
536
619
|
? this.options.autoExtendProjectExtents.excludeOutliers
|
|
537
620
|
: false;
|
|
538
|
-
// If excludeOutliers is true, use the extents without outliers.
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
621
|
+
// If excludeOutliers is true, use the extents without outliers.
|
|
622
|
+
// Otherwise prefer extentsWithOutliers, but fall back to extents if it's undefined or a null range.
|
|
623
|
+
const extentsWithOutliers = computedProjectExtents.extentsWithOutliers;
|
|
624
|
+
const useExtentsWithOutliers = !excludeOutliers && extentsWithOutliers && !extentsWithOutliers.isNull;
|
|
625
|
+
const newProjectExtents = useExtentsWithOutliers
|
|
626
|
+
? extentsWithOutliers
|
|
627
|
+
: computedProjectExtents.extents;
|
|
543
628
|
if (!newProjectExtents.isAlmostEqual(this.targetDb.projectExtents)) {
|
|
544
|
-
this.
|
|
629
|
+
this._editTxn.updateProjectExtents(newProjectExtents);
|
|
545
630
|
core_bentley_1.Logger.logInfo(loggerCategory, `Updated projectExtents=${JSON.stringify(this.targetDb.projectExtents)}`);
|
|
546
631
|
}
|
|
547
632
|
if (!excludeOutliers &&
|
|
@@ -566,7 +651,6 @@ class IModelImporter {
|
|
|
566
651
|
*/
|
|
567
652
|
optimizeGeometry(options) {
|
|
568
653
|
if (options.inlineUniqueGeometryParts) {
|
|
569
|
-
/* eslint-disable-next-line @typescript-eslint/no-deprecated */
|
|
570
654
|
const result = this.targetDb.inlineGeometryParts();
|
|
571
655
|
core_bentley_1.Logger.logInfo(loggerCategory, `Inlined ${result.numRefsInlined} references to ${result.numCandidateParts} geometry parts and deleted ${result.numPartsDeleted} parts.`);
|
|
572
656
|
}
|
|
@@ -575,7 +659,7 @@ class IModelImporter {
|
|
|
575
659
|
for (const [elementId, codeValue] of this._duplicateCodeValueMap) {
|
|
576
660
|
const element = this.targetDb.elements.getElement(elementId);
|
|
577
661
|
element.code.value = codeValue;
|
|
578
|
-
element.
|
|
662
|
+
this._editTxn.updateElement(element.toJSON());
|
|
579
663
|
}
|
|
580
664
|
this._duplicateCodeValueMap.clear();
|
|
581
665
|
}
|
|
@@ -583,7 +667,8 @@ class IModelImporter {
|
|
|
583
667
|
* Needs to be called to perform necessary cleanup operations.
|
|
584
668
|
* By not calling `finalize` there is a risk that data imported into targetDb will not be as expected.
|
|
585
669
|
*
|
|
586
|
-
* @note
|
|
670
|
+
* @note [[IModelTransformer.process]] invokes this method automatically. Call it explicitly after
|
|
671
|
+
* composing the transformer's lower-level subset processing methods.
|
|
587
672
|
*/
|
|
588
673
|
finalize() {
|
|
589
674
|
this.resolveDuplicateCodeValues();
|
|
@@ -598,22 +683,26 @@ exports.IModelImporter = IModelImporter;
|
|
|
598
683
|
*/
|
|
599
684
|
function hasEntityChanged(entity, entityProps, namesToIgnore) {
|
|
600
685
|
let changed = false;
|
|
601
|
-
entity.
|
|
686
|
+
const entityClass = entity.iModel.schemaContext.getSchemaItemSync(entity.schemaItemKey);
|
|
687
|
+
(0, node_assert_1.strict)(ecschema_metadata_1.EntityClass.isEntityClass(entityClass) ||
|
|
688
|
+
ecschema_metadata_1.RelationshipClass.isRelationshipClass(entityClass), `Cannot get metadata for ${entity.classFullName}.`);
|
|
689
|
+
for (const property of entityClass.getPropertiesSync()) {
|
|
690
|
+
const propertyName = property.name;
|
|
602
691
|
if (!changed) {
|
|
603
692
|
if (namesToIgnore && namesToIgnore.has(propertyName)) {
|
|
604
693
|
// skip
|
|
605
694
|
}
|
|
606
|
-
else if (
|
|
607
|
-
changed = hasBinaryValueChanged(entity.asAny[propertyName], entityProps[propertyName]);
|
|
695
|
+
else if (ecschema_metadata_1.PropertyType.Binary === property.propertyType) {
|
|
696
|
+
changed = hasBinaryValueChanged(entity.asAny[core_common_1.ECJsNames.toJsName(propertyName)], entityProps[core_common_1.ECJsNames.toJsName(propertyName)]);
|
|
608
697
|
}
|
|
609
|
-
else if (
|
|
610
|
-
changed = hasNavigationValueChanged(entity.asAny[propertyName], entityProps[propertyName]);
|
|
698
|
+
else if (property.isNavigation()) {
|
|
699
|
+
changed = hasNavigationValueChanged(entity.asAny[core_common_1.ECJsNames.toJsName(propertyName)], entityProps[core_common_1.ECJsNames.toJsName(propertyName)]);
|
|
611
700
|
}
|
|
612
701
|
else {
|
|
613
|
-
changed = hasValueChanged(entity.asAny[propertyName], entityProps[propertyName]);
|
|
702
|
+
changed = hasValueChanged(entity.asAny[core_common_1.ECJsNames.toJsName(propertyName)], entityProps[core_common_1.ECJsNames.toJsName(propertyName)]);
|
|
614
703
|
}
|
|
615
704
|
}
|
|
616
|
-
}
|
|
705
|
+
}
|
|
617
706
|
return changed;
|
|
618
707
|
}
|
|
619
708
|
/** Returns true if the specified binary values are different. */
|
|
@@ -643,9 +732,21 @@ function isDefaultSubCategory(props) {
|
|
|
643
732
|
if (props.id === undefined)
|
|
644
733
|
return false;
|
|
645
734
|
if (!core_bentley_1.Id64.isId64(props.id))
|
|
646
|
-
|
|
735
|
+
core_bentley_1.ITwinError.throwError({
|
|
736
|
+
iTwinErrorId: {
|
|
737
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
738
|
+
key: IModelTransformerError_1.IModelTransformerError.InvalidSubCategory,
|
|
739
|
+
},
|
|
740
|
+
message: "subcategory had invalid id",
|
|
741
|
+
});
|
|
647
742
|
if (props.parent?.id === undefined)
|
|
648
|
-
|
|
743
|
+
core_bentley_1.ITwinError.throwError({
|
|
744
|
+
iTwinErrorId: {
|
|
745
|
+
scope: IModelTransformerError_1.IModelTransformerErrorScope,
|
|
746
|
+
key: IModelTransformerError_1.IModelTransformerError.InvalidSubCategory,
|
|
747
|
+
},
|
|
748
|
+
message: `subcategory with id ${props.id} had no parent`,
|
|
749
|
+
});
|
|
649
750
|
return props.id === core_backend_1.IModelDb.getDefaultSubCategoryId(props.parent.id);
|
|
650
751
|
}
|
|
651
752
|
//# sourceMappingURL=IModelImporter.js.map
|