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