@itwin/imodel-transformer 2.0.0-dev.60 → 2.0.0-dev.61

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.
@@ -1,11 +1,30 @@
1
- import { Id64Set, Id64String } from "@itwin/core-bentley";
1
+ import { Id64Array, Id64String } from "@itwin/core-bentley";
2
2
  import { IModelDb } from "@itwin/core-backend";
3
- /** Finds the target roots required for native bulk deletion.
3
+ /** Native deletion calls needed to delete a set of element trees without a partial result.
4
+ * @internal
5
+ */
6
+ export interface BulkDeletePlan {
7
+ /** Roots for each native deletion call, in execution order. Empty when nothing needs deleting. */
8
+ readonly phases: readonly Id64Array[];
9
+ /** Elements kept because an element outside the deleted trees still references them, each mapped to one such
10
+ * referencing element. Their child elements and sub-models, and the elements whose deletion would delete them,
11
+ * are kept too.
12
+ */
13
+ readonly keptReferences: ReadonlyMap<Id64String, Id64String>;
14
+ }
15
+ /** Plans native bulk deletion of the specified element trees.
16
+ *
17
+ * An element that something outside the deleted trees still references is kept, together with what it
18
+ * needs to stay valid, and the rest is deleted. Keeping elements can leave new outside references, so the
19
+ * plan repeats until none remain.
4
20
  *
5
- * Native deletion already cascades through child elements and modeled contents. This query follows
6
- * those dependencies to find top-level elements whose codes are scoped by an element in a deleted
7
- * tree. Each code-dependent element becomes another native deletion root.
21
+ * Native validation checks each root against the iModel before the call, so a root is refused when its tree
22
+ * contains a definition, such as a category or a view, that a non-definition element in the same call still
23
+ * uses. The plan deletes those users in an earlier call than the definitions they use. Validation stays enabled
24
+ * for every call, so a reference this plan does not know about fails loudly instead of leaving a dangling
25
+ * reference. That includes elements outside the trees whose geometry uses a definition in them, such as a
26
+ * geometry part: only native code can read geometry, so those uses are not checked in advance.
8
27
  * @internal
9
28
  */
10
- export declare function findBulkDeleteRoots(targetDb: IModelDb, elementIds: ReadonlySet<Id64String>): Promise<Id64Set>;
29
+ export declare function planBulkDelete(targetDb: IModelDb, elementIds: ReadonlySet<Id64String>): Promise<BulkDeletePlan>;
11
30
  //# sourceMappingURL=ElementBulkDelete.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ElementBulkDelete.d.ts","sourceRoot":"","sources":["../../src/ElementBulkDelete.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,GAClC,OAAO,CAAC,OAAO,CAAC,CAsClB"}
1
+ {"version":3,"file":"ElementBulkDelete.d.ts","sourceRoot":"","sources":["../../src/ElementBulkDelete.ts"],"names":[],"mappings":"AAKA,OAAO,EAAU,SAAS,EAAW,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE7E,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kGAAkG;IAClG,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC;;;OAGG;IACH,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;CAC9D;AASD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,WAAW,CAAC,UAAU,CAAC,GAClC,OAAO,CAAC,cAAc,CAAC,CAkCzB"}
@@ -4,27 +4,144 @@
4
4
  * See LICENSE.md in the project root for license terms and full copyright notice.
5
5
  *--------------------------------------------------------------------------------------------*/
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.findBulkDeleteRoots = findBulkDeleteRoots;
7
+ exports.planBulkDelete = planBulkDelete;
8
+ const core_bentley_1 = require("@itwin/core-bentley");
8
9
  const core_common_1 = require("@itwin/core-common");
9
- /** Finds the target roots required for native bulk deletion.
10
+ /** Plans native bulk deletion of the specified element trees.
10
11
  *
11
- * Native deletion already cascades through child elements and modeled contents. This query follows
12
- * those dependencies to find top-level elements whose codes are scoped by an element in a deleted
13
- * tree. Each code-dependent element becomes another native deletion root.
12
+ * An element that something outside the deleted trees still references is kept, together with what it
13
+ * needs to stay valid, and the rest is deleted. Keeping elements can leave new outside references, so the
14
+ * plan repeats until none remain.
15
+ *
16
+ * Native validation checks each root against the iModel before the call, so a root is refused when its tree
17
+ * contains a definition, such as a category or a view, that a non-definition element in the same call still
18
+ * uses. The plan deletes those users in an earlier call than the definitions they use. Validation stays enabled
19
+ * for every call, so a reference this plan does not know about fails loudly instead of leaving a dangling
20
+ * reference. That includes elements outside the trees whose geometry uses a definition in them, such as a
21
+ * geometry part: only native code can read geometry, so those uses are not checked in advance.
14
22
  * @internal
15
23
  */
16
- async function findBulkDeleteRoots(targetDb, elementIds) {
17
- const deleteRoots = new Set();
24
+ async function planBulkDelete(targetDb, elementIds) {
25
+ const requestedIds = new Set(elementIds);
26
+ const keptReferences = new Map();
27
+ for (;;) {
28
+ const trees = await queryDeletionTrees(targetDb, requestedIds);
29
+ if (trees.roots.size === 0)
30
+ return { phases: [], keptReferences };
31
+ const references = await queryReferences(targetDb, trees.rootsByElement.keys());
32
+ const blockedIds = new Set();
33
+ for (const { referencingId, referencedId } of references.references) {
34
+ if (trees.rootsByElement.has(referencingId))
35
+ continue;
36
+ blockedIds.add(referencedId);
37
+ if (!keptReferences.has(referencedId))
38
+ keptReferences.set(referencedId, referencingId);
39
+ }
40
+ if (blockedIds.size === 0)
41
+ return {
42
+ phases: await planPhases(targetDb, trees, references),
43
+ keptReferences,
44
+ };
45
+ // Every blocked element is reached from a requested element, and queryKeptElements walks back up to it,
46
+ // so each pass removes at least one requested element and the loop ends.
47
+ const requestedCount = requestedIds.size;
48
+ for (const id of await queryKeptElements(targetDb, blockedIds))
49
+ requestedIds.delete(id);
50
+ (0, core_bentley_1.assert)(requestedIds.size < requestedCount, "Keeping referenced elements must remove a requested element");
51
+ }
52
+ }
53
+ /** Orders the roots of deletion trees that nothing outside them references into native calls. */
54
+ async function planPhases(targetDb, trees, { references, geometryDefinitionIds }) {
55
+ // Elements in the trees that use a definition that is also in the trees. Native validation refuses the definition while they exist.
56
+ const usersOfDeletedDefinitions = new Set();
57
+ // Roots whose trees contain such a definition. They must be deleted after its users.
58
+ const rootsWithUsedDefinitions = new Set();
59
+ const addUsedDefinition = (definitionId) => {
60
+ for (const rootId of trees.rootsByElement.get(definitionId) ?? [])
61
+ rootsWithUsedDefinitions.add(rootId);
62
+ };
63
+ const sameCallReferences = [];
64
+ for (const reference of references) {
65
+ if (reference.usersFirst) {
66
+ usersOfDeletedDefinitions.add(reference.referencingId);
67
+ addUsedDefinition(reference.referencedId);
68
+ }
69
+ else {
70
+ sameCallReferences.push(reference);
71
+ }
72
+ }
73
+ // Only native code can tell which geometry uses a geometry part, material, texture, line style, or sub-category,
74
+ // so every geometric element in the trees counts as a user of every such definition. Deleting the trees that
75
+ // contain those definitions last is enough unless one of them also contains a geometric element; only then are
76
+ // all geometric elements queried, to delete them as roots of their own.
77
+ const geometryRoots = new Set();
78
+ for (const id of geometryDefinitionIds)
79
+ for (const rootId of trees.rootsByElement.get(id) ?? [])
80
+ geometryRoots.add(rootId);
81
+ if (geometryRoots.size > 0) {
82
+ const elementsInGeometryTrees = [...trees.rootsByElement]
83
+ .filter(([, rootIds]) => rootIds.some((id) => geometryRoots.has(id)))
84
+ .map(([id]) => id);
85
+ if ((await queryGeometricElements(targetDb, elementsInGeometryTrees)).length >
86
+ 0)
87
+ for (const id of await queryGeometricElements(targetDb, trees.rootsByElement.keys()))
88
+ usersOfDeletedDefinitions.add(id);
89
+ for (const rootId of geometryRoots)
90
+ rootsWithUsedDefinitions.add(rootId);
91
+ }
92
+ if (rootsWithUsedDefinitions.size === 0)
93
+ return [[...trees.roots]];
94
+ // True when a root deleted in the last call removes the element.
95
+ const isInTreeWithUsedDefinition = (id) => (trees.rootsByElement.get(id) ?? []).some((rootId) => rootsWithUsedDefinitions.has(rootId));
96
+ // True when a root deleted in the first call removes the element. An element in overlapping trees can satisfy both checks.
97
+ const isInOtherTree = (id) => (trees.rootsByElement.get(id) ?? []).some((rootId) => !rootsWithUsedDefinitions.has(rootId));
98
+ // Deleting the other roots first works unless a user shares a tree with a used definition, or an other tree
99
+ // contains an element that an element deleted later references, such as its code scope.
100
+ const canDeleteOtherRootsFirst = ![...usersOfDeletedDefinitions].some(isInTreeWithUsedDefinition) &&
101
+ !sameCallReferences.some(({ referencingId, referencedId }) => isInTreeWithUsedDefinition(referencingId) && isInOtherTree(referencedId));
102
+ if (canDeleteOtherRootsFirst) {
103
+ // There are no other roots only when every tree contains a geometry definition and nothing in the trees uses a
104
+ // definition through a queried reference.
105
+ const otherRoots = [...trees.roots].filter((id) => !rootsWithUsedDefinitions.has(id));
106
+ return otherRoots.length > 0
107
+ ? [otherRoots, [...rootsWithUsedDefinitions]]
108
+ : [[...rootsWithUsedDefinitions]];
109
+ }
110
+ // Otherwise delete the users and their code dependents as roots of their own. Core refuses to delete an
111
+ // element whose code scopes an element deleted in a later call, so the first call also takes code dependents
112
+ // that have a parent. They are all in the trees; one outside them would have kept its code scope above.
113
+ const userTrees = await queryDeletionTrees(targetDb, usersOfDeletedDefinitions, true);
114
+ const remainingRoots = [...trees.roots].filter((id) => !userTrees.rootsByElement.has(id));
115
+ const phases = [[...userTrees.roots]];
116
+ if (remainingRoots.length > 0)
117
+ phases.push(remainingRoots);
118
+ return phases;
119
+ }
120
+ /** Finds the native deletion roots and every element their deletion removes.
121
+ *
122
+ * Native deletion already cascades through child elements and modeled contents. This query follows
123
+ * those dependencies to find elements whose codes are scoped by an element in a deleted tree. Each
124
+ * code-dependent element becomes another native deletion root. Only top-level code dependents are
125
+ * included unless `includeParentedCodeDependents` is true.
126
+ */
127
+ async function queryDeletionTrees(targetDb, elementIds, includeParentedCodeDependents = false) {
128
+ const roots = new Set();
129
+ // An element has more than one root only when requested trees overlap. UNION in the query already removes duplicate
130
+ // (element, root) pairs, so an array holds distinct roots without allocating a Set per element.
131
+ const rootsByElement = new Map();
18
132
  // CascadeIds pairs each traversed element with a root that the native API must delete. The anchor
19
- // adds requested roots that still exist. Recursive branches walk child elements and modeled
20
- // contents while preserving DeleteRootId. A top-level element whose code is scoped by anything
21
- // already traversed becomes a new root, so recursion also covers its tree and code dependents.
22
- // DeleteRoots returns only the roots because native deletion performs the child and model cascade.
133
+ // adds requested elements that still exist, except those whose parent or modeled element is also
134
+ // requested: the recursion reaches them anyway, and anchoring them too would walk a nested tree once
135
+ // per requested ancestor. Recursive branches walk child elements and modeled contents while
136
+ // preserving DeleteRootId. An element whose code is scoped by anything already traversed becomes a
137
+ // new root, so recursion also covers its tree and code dependents.
23
138
  const query = `
24
139
  WITH RECURSIVE CascadeIds(Id, DeleteRootId) AS (
25
140
  SELECT element.ECInstanceId, element.ECInstanceId
26
141
  FROM bis.Element element
27
142
  INNER JOIN IdSet(:elementIds) ids ON ids.id = element.ECInstanceId
143
+ WHERE (element.Parent.Id IS NULL OR element.Parent.Id NOT IN (SELECT id FROM IdSet(:elementIds)))
144
+ AND element.Model.Id NOT IN (SELECT id FROM IdSet(:elementIds))
28
145
  UNION
29
146
  SELECT child.ECInstanceId, deletionParent.DeleteRootId
30
147
  FROM bis.Element child
@@ -37,19 +154,205 @@ async function findBulkDeleteRoots(targetDb, elementIds) {
37
154
  SELECT codeDependent.ECInstanceId, codeDependent.ECInstanceId
38
155
  FROM bis.Element codeDependent
39
156
  INNER JOIN CascadeIds scope ON codeDependent.CodeScope.Id = scope.Id
40
- WHERE codeDependent.Parent.Id IS NULL
41
- ),
42
- DeleteRoots(Id) AS (
43
- SELECT DISTINCT DeleteRootId FROM CascadeIds
157
+ ${includeParentedCodeDependents ? "" : "WHERE codeDependent.Parent.Id IS NULL"}
44
158
  )
45
- SELECT Id AS id FROM DeleteRoots
159
+ SELECT Id AS id, DeleteRootId AS rootId FROM CascadeIds
46
160
  `;
47
161
  const params = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
48
162
  for await (const row of targetDb.createQueryReader(query, params, {
49
163
  usePrimaryConn: true,
50
164
  })) {
51
- deleteRoots.add(row.id);
165
+ roots.add(row.rootId);
166
+ const elementRoots = rootsByElement.get(row.id);
167
+ if (elementRoots)
168
+ elementRoots.push(row.rootId);
169
+ else
170
+ rootsByElement.set(row.id, [row.rootId]);
171
+ }
172
+ return { roots, rootsByElement };
173
+ }
174
+ /** Finds the elements to keep so that the blocked elements stay valid: each blocked element and its child
175
+ * elements and sub-model contents, plus every element whose deletion would delete a kept element or leave its
176
+ * parent, model, or code scope dangling.
177
+ *
178
+ * The whole subtree below a blocked element is kept, even when the element is blocked only as a code scope and
179
+ * its children could be deleted. A kept category needs its sub-categories, because the plan can't see geometry
180
+ * outside the trees that uses them, and keeping too much is safe.
181
+ */
182
+ async function queryKeptElements(targetDb, blockedIds) {
183
+ const query = `
184
+ WITH RECURSIVE
185
+ Above(Id) AS (
186
+ SELECT ids.id FROM IdSet(:blockedIds) ids
187
+ UNION
188
+ SELECT element.Parent.Id FROM bis.Element element
189
+ INNER JOIN Above ON element.ECInstanceId = Above.Id
190
+ WHERE element.Parent.Id IS NOT NULL
191
+ UNION
192
+ SELECT element.Model.Id FROM bis.Element element
193
+ INNER JOIN Above ON element.ECInstanceId = Above.Id
194
+ UNION
195
+ SELECT element.CodeScope.Id FROM bis.Element element
196
+ INNER JOIN Above ON element.ECInstanceId = Above.Id
197
+ ),
198
+ Below(Id) AS (
199
+ SELECT ids.id FROM IdSet(:blockedIds) ids
200
+ UNION
201
+ SELECT element.ECInstanceId FROM bis.Element element
202
+ INNER JOIN Below ON element.Parent.Id = Below.Id
203
+ UNION
204
+ SELECT element.ECInstanceId FROM bis.Element element
205
+ INNER JOIN Below ON element.Model.Id = Below.Id
206
+ )
207
+ SELECT Id AS id FROM Above
208
+ UNION
209
+ SELECT Id FROM Below
210
+ `;
211
+ const keptIds = new Set();
212
+ const params = new core_common_1.QueryBinder().bindIdSet("blockedIds", blockedIds);
213
+ for await (const row of targetDb.createQueryReader(query, params, {
214
+ usePrimaryConn: true,
215
+ }))
216
+ keptIds.add(row.id);
217
+ return keptIds;
218
+ }
219
+ /** Finds BisCore references to the specified elements that native deletion validates and that [[queryDeletionTrees]]
220
+ * does not follow. Parent and model references are not included because the deleted trees contain every child and
221
+ * modeled element.
222
+ */
223
+ async function queryReferences(targetDb, elementIds) {
224
+ const references = [];
225
+ const geometryDefinitionIds = [];
226
+ // Any element can be a code scope. Every other validated reference targets a definition element, so those are
227
+ // queried only for the definitions among the elements, which are usually few or none.
228
+ const definitionIds = [];
229
+ const firstQuery = `
230
+ SELECT element.ECInstanceId AS referencingId, element.CodeScope.Id AS referencedId, 0 AS isDefinition
231
+ FROM bis.Element element
232
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = element.CodeScope.Id
233
+ UNION ALL
234
+ SELECT definition.ECInstanceId, definition.ECInstanceId, 1
235
+ FROM bis.DefinitionElement definition
236
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = definition.ECInstanceId
237
+ `;
238
+ for await (const row of targetDb.createQueryReader(firstQuery, new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds), { usePrimaryConn: true })) {
239
+ if (row.isDefinition === 1)
240
+ definitionIds.push(row.referencedId);
241
+ else
242
+ references.push({
243
+ referencingId: row.referencingId,
244
+ referencedId: row.referencedId,
245
+ usersFirst: false,
246
+ });
52
247
  }
53
- return deleteRoots;
248
+ if (definitionIds.length === 0)
249
+ return { references, geometryDefinitionIds };
250
+ // Classes and properties added in later BisCore versions.
251
+ const sectionReferences = await querySectionViewReferences(targetDb);
252
+ // Kind 1: native validation refuses the definition while the referencing element exists, even in the same call.
253
+ // Kind 0: deleting both in the same call is enough. Native validation treats a default sub-category, whose ID
254
+ // follows its category's, as used by the category unless both are deleted.
255
+ // Kind 2: a definition that geometry references, so its users can't be queried.
256
+ const definitionQuery = `
257
+ SELECT element.ECInstanceId AS referencingId, element.Category.Id AS referencedId, 1 AS kind
258
+ FROM bis.GeometricElement3d element
259
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = element.Category.Id
260
+ UNION ALL
261
+ SELECT element.ECInstanceId, element.Category.Id, 1
262
+ FROM bis.GeometricElement2d element
263
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = element.Category.Id
264
+ UNION ALL
265
+ SELECT element.ECInstanceId, element.View.Id, 1
266
+ FROM bis.ViewAttachment element
267
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = element.View.Id
268
+ ${sectionReferences
269
+ .map(({ className, propertyName }) => `
270
+ UNION ALL
271
+ SELECT element.ECInstanceId, element.${propertyName}.Id, 1
272
+ FROM bis.${className} element
273
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = element.${propertyName}.Id`)
274
+ .join("")}
275
+ UNION ALL
276
+ SELECT viewDefinition.ECInstanceId, viewDefinition.DisplayStyle.Id, 0
277
+ FROM bis.ViewDefinition viewDefinition
278
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = viewDefinition.DisplayStyle.Id
279
+ UNION ALL
280
+ SELECT viewDefinition.ECInstanceId, viewDefinition.CategorySelector.Id, 0
281
+ FROM bis.ViewDefinition viewDefinition
282
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = viewDefinition.CategorySelector.Id
283
+ UNION ALL
284
+ SELECT viewDefinition.ECInstanceId, viewDefinition.ModelSelector.Id, 0
285
+ FROM bis.SpatialViewDefinition viewDefinition
286
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = viewDefinition.ModelSelector.Id
287
+ UNION ALL
288
+ SELECT subCategory.Parent.Id, subCategory.ECInstanceId, 0
289
+ FROM bis.SubCategory subCategory
290
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = subCategory.ECInstanceId
291
+ WHERE CAST(subCategory.ECInstanceId AS INTEGER) = CAST(subCategory.Parent.Id AS INTEGER) + 1
292
+ UNION ALL
293
+ SELECT subCategory.ECInstanceId, subCategory.ECInstanceId, 2
294
+ FROM bis.SubCategory subCategory
295
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = subCategory.ECInstanceId
296
+ WHERE CAST(subCategory.ECInstanceId AS INTEGER) <> CAST(subCategory.Parent.Id AS INTEGER) + 1
297
+ ${["GeometryPart", "RenderMaterial", "Texture", "LineStyle"]
298
+ .map((className) => `
299
+ UNION ALL
300
+ SELECT element.ECInstanceId, element.ECInstanceId, 2
301
+ FROM bis.${className} element
302
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = element.ECInstanceId`)
303
+ .join("")}
304
+ `;
305
+ for await (const row of targetDb.createQueryReader(definitionQuery, new core_common_1.QueryBinder().bindIdSet("elementIds", definitionIds), { usePrimaryConn: true })) {
306
+ if (row.kind === 2)
307
+ geometryDefinitionIds.push(row.referencedId);
308
+ else
309
+ references.push({
310
+ referencingId: row.referencingId,
311
+ referencedId: row.referencedId,
312
+ usersFirst: row.kind === 1,
313
+ });
314
+ }
315
+ return { references, geometryDefinitionIds };
316
+ }
317
+ /** Finds the BisCore section classes and view properties that exist in the iModel's schema. */
318
+ async function querySectionViewReferences(targetDb) {
319
+ const query = `
320
+ SELECT classDef.Name AS className, propertyDef.Name AS propertyName
321
+ FROM meta.ECPropertyDef propertyDef
322
+ INNER JOIN meta.ECClassDef classDef ON classDef.ECInstanceId = propertyDef.Class.Id
323
+ INNER JOIN meta.ECSchemaDef schemaDef ON schemaDef.ECInstanceId = classDef.Schema.Id
324
+ WHERE schemaDef.Name = 'BisCore'
325
+ AND ((classDef.Name = 'SectionDrawing' AND propertyDef.Name = 'SpatialView')
326
+ OR (classDef.Name = 'SectionDrawingLocation' AND propertyDef.Name = 'SectionView'))
327
+ `;
328
+ const references = [];
329
+ for await (const row of targetDb.createQueryReader(query, undefined, {
330
+ usePrimaryConn: true,
331
+ }))
332
+ references.push({
333
+ className: row.className,
334
+ propertyName: row.propertyName,
335
+ });
336
+ return references;
337
+ }
338
+ /** Finds the 2D and 3D geometric elements among the specified elements. */
339
+ async function queryGeometricElements(targetDb, elementIds) {
340
+ // Joining the abstract bis.GeometricElement with an IdSet is quadratic, so query its 3D and 2D subclasses.
341
+ const query = `
342
+ SELECT element.ECInstanceId AS id
343
+ FROM bis.GeometricElement3d element
344
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = element.ECInstanceId
345
+ UNION ALL
346
+ SELECT element.ECInstanceId
347
+ FROM bis.GeometricElement2d element
348
+ INNER JOIN IdSet(:elementIds) ids ON ids.id = element.ECInstanceId
349
+ `;
350
+ const ids = [];
351
+ const params = new core_common_1.QueryBinder().bindIdSet("elementIds", elementIds);
352
+ for await (const row of targetDb.createQueryReader(query, params, {
353
+ usePrimaryConn: true,
354
+ }))
355
+ ids.push(row.id);
356
+ return ids;
54
357
  }
55
358
  //# sourceMappingURL=ElementBulkDelete.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ElementBulkDelete.js","sourceRoot":"","sources":["../../src/ElementBulkDelete.ts"],"names":[],"mappings":";AAAA;;;gGAGgG;;;AAGhG,oDAAiD;AAGjD;;;;;;GAMG;AACI,KAAK,8BACV,QAAkB,EAClB,UAAmC;IAEnC,MAAM,WAAW,GAAY,IAAI,GAAG,EAAc,CAAC;IACnD,kGAAkG;IAClG,4FAA4F;IAC5F,+FAA+F;IAC/F,+FAA+F;IAC/F,mGAAmG;IACnG,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;GAuBb,CAAC;IACF,MAAM,MAAM,GAAG,IAAI,yBAAW,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACrE,IAAI,KAAK,EAAE,MAAM,GAAG,IAAI,QAAQ,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE;QAChE,cAAc,EAAE,IAAI;KACrB,CAAC,EAAE,CAAC;QACH,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { Id64Set, Id64String } from \"@itwin/core-bentley\";\nimport { QueryBinder } from \"@itwin/core-common\";\nimport { IModelDb } from \"@itwin/core-backend\";\n\n/** Finds the target roots required for native bulk deletion.\n *\n * Native deletion already cascades through child elements and modeled contents. This query follows\n * those dependencies to find top-level elements whose codes are scoped by an element in a deleted\n * tree. Each code-dependent element becomes another native deletion root.\n * @internal\n */\nexport async function findBulkDeleteRoots(\n targetDb: IModelDb,\n elementIds: ReadonlySet<Id64String>\n): Promise<Id64Set> {\n const deleteRoots: Id64Set = new Set<Id64String>();\n // CascadeIds pairs each traversed element with a root that the native API must delete. The anchor\n // adds requested roots that still exist. Recursive branches walk child elements and modeled\n // contents while preserving DeleteRootId. A top-level element whose code is scoped by anything\n // already traversed becomes a new root, so recursion also covers its tree and code dependents.\n // DeleteRoots returns only the roots because native deletion performs the child and model cascade.\n const query = `\n WITH RECURSIVE CascadeIds(Id, DeleteRootId) AS (\n SELECT element.ECInstanceId, element.ECInstanceId\n FROM bis.Element element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.ECInstanceId\n UNION\n SELECT child.ECInstanceId, deletionParent.DeleteRootId\n FROM bis.Element child\n INNER JOIN CascadeIds deletionParent ON child.Parent.Id = deletionParent.Id\n UNION\n SELECT modelElement.ECInstanceId, modeledElement.DeleteRootId\n FROM bis.Element modelElement\n INNER JOIN CascadeIds modeledElement ON modelElement.Model.Id = modeledElement.Id\n UNION\n SELECT codeDependent.ECInstanceId, codeDependent.ECInstanceId\n FROM bis.Element codeDependent\n INNER JOIN CascadeIds scope ON codeDependent.CodeScope.Id = scope.Id\n WHERE codeDependent.Parent.Id IS NULL\n ),\n DeleteRoots(Id) AS (\n SELECT DISTINCT DeleteRootId FROM CascadeIds\n )\n SELECT Id AS id FROM DeleteRoots\n `;\n const params = new QueryBinder().bindIdSet(\"elementIds\", elementIds);\n for await (const row of targetDb.createQueryReader(query, params, {\n usePrimaryConn: true,\n })) {\n deleteRoots.add(row.id);\n }\n return deleteRoots;\n}\n"]}
1
+ {"version":3,"file":"ElementBulkDelete.js","sourceRoot":"","sources":["../../src/ElementBulkDelete.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { assert, Id64Array, Id64Set, Id64String } from \"@itwin/core-bentley\";\nimport { QueryBinder } from \"@itwin/core-common\";\nimport { IModelDb } from \"@itwin/core-backend\";\n\n/** Native deletion calls needed to delete a set of element trees without a partial result.\n * @internal\n */\nexport interface BulkDeletePlan {\n /** Roots for each native deletion call, in execution order. Empty when nothing needs deleting. */\n readonly phases: readonly Id64Array[];\n /** Elements kept because an element outside the deleted trees still references them, each mapped to one such\n * referencing element. Their child elements and sub-models, and the elements whose deletion would delete them,\n * are kept too.\n */\n readonly keptReferences: ReadonlyMap<Id64String, Id64String>;\n}\n\ninterface DeletionTrees {\n /** Roots that the native API must receive. */\n readonly roots: Id64Set;\n /** Every element that deleting the roots removes, mapped to the roots whose trees contain it. */\n readonly rootsByElement: ReadonlyMap<Id64String, readonly Id64String[]>;\n}\n\n/** Plans native bulk deletion of the specified element trees.\n *\n * An element that something outside the deleted trees still references is kept, together with what it\n * needs to stay valid, and the rest is deleted. Keeping elements can leave new outside references, so the\n * plan repeats until none remain.\n *\n * Native validation checks each root against the iModel before the call, so a root is refused when its tree\n * contains a definition, such as a category or a view, that a non-definition element in the same call still\n * uses. The plan deletes those users in an earlier call than the definitions they use. Validation stays enabled\n * for every call, so a reference this plan does not know about fails loudly instead of leaving a dangling\n * reference. That includes elements outside the trees whose geometry uses a definition in them, such as a\n * geometry part: only native code can read geometry, so those uses are not checked in advance.\n * @internal\n */\nexport async function planBulkDelete(\n targetDb: IModelDb,\n elementIds: ReadonlySet<Id64String>\n): Promise<BulkDeletePlan> {\n const requestedIds = new Set(elementIds);\n const keptReferences = new Map<Id64String, Id64String>();\n for (;;) {\n const trees = await queryDeletionTrees(targetDb, requestedIds);\n if (trees.roots.size === 0) return { phases: [], keptReferences };\n\n const references = await queryReferences(\n targetDb,\n trees.rootsByElement.keys()\n );\n const blockedIds = new Set<Id64String>();\n for (const { referencingId, referencedId } of references.references) {\n if (trees.rootsByElement.has(referencingId)) continue;\n blockedIds.add(referencedId);\n if (!keptReferences.has(referencedId))\n keptReferences.set(referencedId, referencingId);\n }\n if (blockedIds.size === 0)\n return {\n phases: await planPhases(targetDb, trees, references),\n keptReferences,\n };\n\n // Every blocked element is reached from a requested element, and queryKeptElements walks back up to it,\n // so each pass removes at least one requested element and the loop ends.\n const requestedCount = requestedIds.size;\n for (const id of await queryKeptElements(targetDb, blockedIds))\n requestedIds.delete(id);\n assert(\n requestedIds.size < requestedCount,\n \"Keeping referenced elements must remove a requested element\"\n );\n }\n}\n\n/** Orders the roots of deletion trees that nothing outside them references into native calls. */\nasync function planPhases(\n targetDb: IModelDb,\n trees: DeletionTrees,\n { references, geometryDefinitionIds }: TreeReferences\n): Promise<Id64Array[]> {\n // Elements in the trees that use a definition that is also in the trees. Native validation refuses the definition while they exist.\n const usersOfDeletedDefinitions = new Set<Id64String>();\n // Roots whose trees contain such a definition. They must be deleted after its users.\n const rootsWithUsedDefinitions = new Set<Id64String>();\n const addUsedDefinition = (definitionId: Id64String) => {\n for (const rootId of trees.rootsByElement.get(definitionId) ?? [])\n rootsWithUsedDefinitions.add(rootId);\n };\n const sameCallReferences: TreeReference[] = [];\n for (const reference of references) {\n if (reference.usersFirst) {\n usersOfDeletedDefinitions.add(reference.referencingId);\n addUsedDefinition(reference.referencedId);\n } else {\n sameCallReferences.push(reference);\n }\n }\n // Only native code can tell which geometry uses a geometry part, material, texture, line style, or sub-category,\n // so every geometric element in the trees counts as a user of every such definition. Deleting the trees that\n // contain those definitions last is enough unless one of them also contains a geometric element; only then are\n // all geometric elements queried, to delete them as roots of their own.\n const geometryRoots = new Set<Id64String>();\n for (const id of geometryDefinitionIds)\n for (const rootId of trees.rootsByElement.get(id) ?? [])\n geometryRoots.add(rootId);\n if (geometryRoots.size > 0) {\n const elementsInGeometryTrees = [...trees.rootsByElement]\n .filter(([, rootIds]) => rootIds.some((id) => geometryRoots.has(id)))\n .map(([id]) => id);\n if (\n (await queryGeometricElements(targetDb, elementsInGeometryTrees)).length >\n 0\n )\n for (const id of await queryGeometricElements(\n targetDb,\n trees.rootsByElement.keys()\n ))\n usersOfDeletedDefinitions.add(id);\n for (const rootId of geometryRoots) rootsWithUsedDefinitions.add(rootId);\n }\n if (rootsWithUsedDefinitions.size === 0) return [[...trees.roots]];\n // True when a root deleted in the last call removes the element.\n const isInTreeWithUsedDefinition = (id: Id64String) =>\n (trees.rootsByElement.get(id) ?? []).some((rootId) =>\n rootsWithUsedDefinitions.has(rootId)\n );\n // True when a root deleted in the first call removes the element. An element in overlapping trees can satisfy both checks.\n const isInOtherTree = (id: Id64String) =>\n (trees.rootsByElement.get(id) ?? []).some(\n (rootId) => !rootsWithUsedDefinitions.has(rootId)\n );\n // Deleting the other roots first works unless a user shares a tree with a used definition, or an other tree\n // contains an element that an element deleted later references, such as its code scope.\n const canDeleteOtherRootsFirst =\n ![...usersOfDeletedDefinitions].some(isInTreeWithUsedDefinition) &&\n !sameCallReferences.some(\n ({ referencingId, referencedId }) =>\n isInTreeWithUsedDefinition(referencingId) && isInOtherTree(referencedId)\n );\n if (canDeleteOtherRootsFirst) {\n // There are no other roots only when every tree contains a geometry definition and nothing in the trees uses a\n // definition through a queried reference.\n const otherRoots = [...trees.roots].filter(\n (id) => !rootsWithUsedDefinitions.has(id)\n );\n return otherRoots.length > 0\n ? [otherRoots, [...rootsWithUsedDefinitions]]\n : [[...rootsWithUsedDefinitions]];\n }\n\n // Otherwise delete the users and their code dependents as roots of their own. Core refuses to delete an\n // element whose code scopes an element deleted in a later call, so the first call also takes code dependents\n // that have a parent. They are all in the trees; one outside them would have kept its code scope above.\n const userTrees = await queryDeletionTrees(\n targetDb,\n usersOfDeletedDefinitions,\n true\n );\n const remainingRoots = [...trees.roots].filter(\n (id) => !userTrees.rootsByElement.has(id)\n );\n const phases = [[...userTrees.roots]];\n if (remainingRoots.length > 0) phases.push(remainingRoots);\n return phases;\n}\n\n/** Finds the native deletion roots and every element their deletion removes.\n *\n * Native deletion already cascades through child elements and modeled contents. This query follows\n * those dependencies to find elements whose codes are scoped by an element in a deleted tree. Each\n * code-dependent element becomes another native deletion root. Only top-level code dependents are\n * included unless `includeParentedCodeDependents` is true.\n */\nasync function queryDeletionTrees(\n targetDb: IModelDb,\n elementIds: ReadonlySet<Id64String>,\n includeParentedCodeDependents = false\n): Promise<DeletionTrees> {\n const roots: Id64Set = new Set<Id64String>();\n // An element has more than one root only when requested trees overlap. UNION in the query already removes duplicate\n // (element, root) pairs, so an array holds distinct roots without allocating a Set per element.\n const rootsByElement = new Map<Id64String, Id64String[]>();\n // CascadeIds pairs each traversed element with a root that the native API must delete. The anchor\n // adds requested elements that still exist, except those whose parent or modeled element is also\n // requested: the recursion reaches them anyway, and anchoring them too would walk a nested tree once\n // per requested ancestor. Recursive branches walk child elements and modeled contents while\n // preserving DeleteRootId. An element whose code is scoped by anything already traversed becomes a\n // new root, so recursion also covers its tree and code dependents.\n const query = `\n WITH RECURSIVE CascadeIds(Id, DeleteRootId) AS (\n SELECT element.ECInstanceId, element.ECInstanceId\n FROM bis.Element element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.ECInstanceId\n WHERE (element.Parent.Id IS NULL OR element.Parent.Id NOT IN (SELECT id FROM IdSet(:elementIds)))\n AND element.Model.Id NOT IN (SELECT id FROM IdSet(:elementIds))\n UNION\n SELECT child.ECInstanceId, deletionParent.DeleteRootId\n FROM bis.Element child\n INNER JOIN CascadeIds deletionParent ON child.Parent.Id = deletionParent.Id\n UNION\n SELECT modelElement.ECInstanceId, modeledElement.DeleteRootId\n FROM bis.Element modelElement\n INNER JOIN CascadeIds modeledElement ON modelElement.Model.Id = modeledElement.Id\n UNION\n SELECT codeDependent.ECInstanceId, codeDependent.ECInstanceId\n FROM bis.Element codeDependent\n INNER JOIN CascadeIds scope ON codeDependent.CodeScope.Id = scope.Id\n ${includeParentedCodeDependents ? \"\" : \"WHERE codeDependent.Parent.Id IS NULL\"}\n )\n SELECT Id AS id, DeleteRootId AS rootId FROM CascadeIds\n `;\n const params = new QueryBinder().bindIdSet(\"elementIds\", elementIds);\n for await (const row of targetDb.createQueryReader(query, params, {\n usePrimaryConn: true,\n })) {\n roots.add(row.rootId);\n const elementRoots = rootsByElement.get(row.id);\n if (elementRoots) elementRoots.push(row.rootId);\n else rootsByElement.set(row.id, [row.rootId]);\n }\n return { roots, rootsByElement };\n}\n\n/** Finds the elements to keep so that the blocked elements stay valid: each blocked element and its child\n * elements and sub-model contents, plus every element whose deletion would delete a kept element or leave its\n * parent, model, or code scope dangling.\n *\n * The whole subtree below a blocked element is kept, even when the element is blocked only as a code scope and\n * its children could be deleted. A kept category needs its sub-categories, because the plan can't see geometry\n * outside the trees that uses them, and keeping too much is safe.\n */\nasync function queryKeptElements(\n targetDb: IModelDb,\n blockedIds: ReadonlySet<Id64String>\n): Promise<Id64Set> {\n const query = `\n WITH RECURSIVE\n Above(Id) AS (\n SELECT ids.id FROM IdSet(:blockedIds) ids\n UNION\n SELECT element.Parent.Id FROM bis.Element element\n INNER JOIN Above ON element.ECInstanceId = Above.Id\n WHERE element.Parent.Id IS NOT NULL\n UNION\n SELECT element.Model.Id FROM bis.Element element\n INNER JOIN Above ON element.ECInstanceId = Above.Id\n UNION\n SELECT element.CodeScope.Id FROM bis.Element element\n INNER JOIN Above ON element.ECInstanceId = Above.Id\n ),\n Below(Id) AS (\n SELECT ids.id FROM IdSet(:blockedIds) ids\n UNION\n SELECT element.ECInstanceId FROM bis.Element element\n INNER JOIN Below ON element.Parent.Id = Below.Id\n UNION\n SELECT element.ECInstanceId FROM bis.Element element\n INNER JOIN Below ON element.Model.Id = Below.Id\n )\n SELECT Id AS id FROM Above\n UNION\n SELECT Id FROM Below\n `;\n const keptIds: Id64Set = new Set<Id64String>();\n const params = new QueryBinder().bindIdSet(\"blockedIds\", blockedIds);\n for await (const row of targetDb.createQueryReader(query, params, {\n usePrimaryConn: true,\n }))\n keptIds.add(row.id);\n return keptIds;\n}\n\ninterface TreeReference {\n readonly referencingId: Id64String;\n readonly referencedId: Id64String;\n /** True when native validation refuses the referenced element while the referencing element exists, even when\n * both are deleted in the same call. False when deleting them in the same call is enough.\n */\n readonly usersFirst: boolean;\n}\n\ninterface TreeReferences {\n readonly references: readonly TreeReference[];\n /** Geometry parts, materials, textures, line styles, and non-default sub-categories in the trees. Geometry\n * references them, so their users can't be queried.\n */\n readonly geometryDefinitionIds: readonly Id64String[];\n}\n\n/** Finds BisCore references to the specified elements that native deletion validates and that [[queryDeletionTrees]]\n * does not follow. Parent and model references are not included because the deleted trees contain every child and\n * modeled element.\n */\nasync function queryReferences(\n targetDb: IModelDb,\n elementIds: Iterable<Id64String>\n): Promise<TreeReferences> {\n const references: TreeReference[] = [];\n const geometryDefinitionIds: Id64String[] = [];\n // Any element can be a code scope. Every other validated reference targets a definition element, so those are\n // queried only for the definitions among the elements, which are usually few or none.\n const definitionIds: Id64String[] = [];\n const firstQuery = `\n SELECT element.ECInstanceId AS referencingId, element.CodeScope.Id AS referencedId, 0 AS isDefinition\n FROM bis.Element element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.CodeScope.Id\n UNION ALL\n SELECT definition.ECInstanceId, definition.ECInstanceId, 1\n FROM bis.DefinitionElement definition\n INNER JOIN IdSet(:elementIds) ids ON ids.id = definition.ECInstanceId\n `;\n for await (const row of targetDb.createQueryReader(\n firstQuery,\n new QueryBinder().bindIdSet(\"elementIds\", elementIds),\n { usePrimaryConn: true }\n )) {\n if (row.isDefinition === 1) definitionIds.push(row.referencedId);\n else\n references.push({\n referencingId: row.referencingId,\n referencedId: row.referencedId,\n usersFirst: false,\n });\n }\n if (definitionIds.length === 0) return { references, geometryDefinitionIds };\n\n // Classes and properties added in later BisCore versions.\n const sectionReferences = await querySectionViewReferences(targetDb);\n // Kind 1: native validation refuses the definition while the referencing element exists, even in the same call.\n // Kind 0: deleting both in the same call is enough. Native validation treats a default sub-category, whose ID\n // follows its category's, as used by the category unless both are deleted.\n // Kind 2: a definition that geometry references, so its users can't be queried.\n const definitionQuery = `\n SELECT element.ECInstanceId AS referencingId, element.Category.Id AS referencedId, 1 AS kind\n FROM bis.GeometricElement3d element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.Category.Id\n UNION ALL\n SELECT element.ECInstanceId, element.Category.Id, 1\n FROM bis.GeometricElement2d element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.Category.Id\n UNION ALL\n SELECT element.ECInstanceId, element.View.Id, 1\n FROM bis.ViewAttachment element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.View.Id\n ${sectionReferences\n .map(\n ({ className, propertyName }) => `\n UNION ALL\n SELECT element.ECInstanceId, element.${propertyName}.Id, 1\n FROM bis.${className} element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.${propertyName}.Id`\n )\n .join(\"\")}\n UNION ALL\n SELECT viewDefinition.ECInstanceId, viewDefinition.DisplayStyle.Id, 0\n FROM bis.ViewDefinition viewDefinition\n INNER JOIN IdSet(:elementIds) ids ON ids.id = viewDefinition.DisplayStyle.Id\n UNION ALL\n SELECT viewDefinition.ECInstanceId, viewDefinition.CategorySelector.Id, 0\n FROM bis.ViewDefinition viewDefinition\n INNER JOIN IdSet(:elementIds) ids ON ids.id = viewDefinition.CategorySelector.Id\n UNION ALL\n SELECT viewDefinition.ECInstanceId, viewDefinition.ModelSelector.Id, 0\n FROM bis.SpatialViewDefinition viewDefinition\n INNER JOIN IdSet(:elementIds) ids ON ids.id = viewDefinition.ModelSelector.Id\n UNION ALL\n SELECT subCategory.Parent.Id, subCategory.ECInstanceId, 0\n FROM bis.SubCategory subCategory\n INNER JOIN IdSet(:elementIds) ids ON ids.id = subCategory.ECInstanceId\n WHERE CAST(subCategory.ECInstanceId AS INTEGER) = CAST(subCategory.Parent.Id AS INTEGER) + 1\n UNION ALL\n SELECT subCategory.ECInstanceId, subCategory.ECInstanceId, 2\n FROM bis.SubCategory subCategory\n INNER JOIN IdSet(:elementIds) ids ON ids.id = subCategory.ECInstanceId\n WHERE CAST(subCategory.ECInstanceId AS INTEGER) <> CAST(subCategory.Parent.Id AS INTEGER) + 1\n ${[\"GeometryPart\", \"RenderMaterial\", \"Texture\", \"LineStyle\"]\n .map(\n (className) => `\n UNION ALL\n SELECT element.ECInstanceId, element.ECInstanceId, 2\n FROM bis.${className} element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.ECInstanceId`\n )\n .join(\"\")}\n `;\n for await (const row of targetDb.createQueryReader(\n definitionQuery,\n new QueryBinder().bindIdSet(\"elementIds\", definitionIds),\n { usePrimaryConn: true }\n )) {\n if (row.kind === 2) geometryDefinitionIds.push(row.referencedId);\n else\n references.push({\n referencingId: row.referencingId,\n referencedId: row.referencedId,\n usersFirst: row.kind === 1,\n });\n }\n return { references, geometryDefinitionIds };\n}\n\n/** Finds the BisCore section classes and view properties that exist in the iModel's schema. */\nasync function querySectionViewReferences(\n targetDb: IModelDb\n): Promise<{ className: string; propertyName: string }[]> {\n const query = `\n SELECT classDef.Name AS className, propertyDef.Name AS propertyName\n FROM meta.ECPropertyDef propertyDef\n INNER JOIN meta.ECClassDef classDef ON classDef.ECInstanceId = propertyDef.Class.Id\n INNER JOIN meta.ECSchemaDef schemaDef ON schemaDef.ECInstanceId = classDef.Schema.Id\n WHERE schemaDef.Name = 'BisCore'\n AND ((classDef.Name = 'SectionDrawing' AND propertyDef.Name = 'SpatialView')\n OR (classDef.Name = 'SectionDrawingLocation' AND propertyDef.Name = 'SectionView'))\n `;\n const references: { className: string; propertyName: string }[] = [];\n for await (const row of targetDb.createQueryReader(query, undefined, {\n usePrimaryConn: true,\n }))\n references.push({\n className: row.className,\n propertyName: row.propertyName,\n });\n return references;\n}\n\n/** Finds the 2D and 3D geometric elements among the specified elements. */\nasync function queryGeometricElements(\n targetDb: IModelDb,\n elementIds: Iterable<Id64String>\n): Promise<Id64String[]> {\n // Joining the abstract bis.GeometricElement with an IdSet is quadratic, so query its 3D and 2D subclasses.\n const query = `\n SELECT element.ECInstanceId AS id\n FROM bis.GeometricElement3d element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.ECInstanceId\n UNION ALL\n SELECT element.ECInstanceId\n FROM bis.GeometricElement2d element\n INNER JOIN IdSet(:elementIds) ids ON ids.id = element.ECInstanceId\n `;\n const ids: Id64String[] = [];\n const params = new QueryBinder().bindIdSet(\"elementIds\", elementIds);\n for await (const row of targetDb.createQueryReader(query, params, {\n usePrimaryConn: true,\n }))\n ids.push(row.id);\n return ids;\n}\n"]}
@@ -166,13 +166,17 @@ export declare class IModelImporter {
166
166
  protected onUpdateElement(elementProps: ElementProps): Promise<void>;
167
167
  /** Deletes one target element tree through [[deleteElements]]. */
168
168
  deleteElement(elementId: Id64String): Promise<void>;
169
- /** Adds roots required by code-scope dependencies, then deletes the target element trees in one native operation.
169
+ /** Adds roots required by code-scope dependencies, then deletes the target element trees in as few native operations as their references allow.
170
+ * Usually one native operation is enough. When a tree contains a definition, such as a category, that another deleted element uses, the elements that use it are deleted first.
171
+ * Elements that something outside the deleted trees still references are kept, with a warning, and the rest are deleted.
170
172
  * @note An override must call `super.onDeleteElements` once to perform the deletion.
171
173
  */
172
174
  protected onDeleteElements(elementIds: ReadonlySet<Id64String>): Promise<void>;
173
- /** Deletes target element trees in one native operation.
175
+ private deleteElementRoots;
176
+ /** Deletes target element trees, using one native operation unless references between the trees require more.
174
177
  * Requested roots in [[doNotUpdateElementIds]] are skipped. This does not prevent an element in that set from being deleted as part of another root's cascade.
175
- * @throws [[ElementBulkDeleteError]] if native deletion fails for any root. A partial failure leaves successful deletions pending in the caller-owned transaction. Abandon the transaction before retrying.
178
+ * Elements that something outside the deleted trees still references are kept, along with their child elements and sub-models and the elements that contain them. A warning lists them.
179
+ * @throws [[ElementBulkDeleteError]] if a native operation fails for any root, for example because geometry outside the deleted trees uses a geometry part in them, or because of a reference in a domain schema. The transformer does not check those references first. Deletions from that and earlier native operations stay pending in the caller-owned transaction. Abandon the transaction before retrying.
176
180
  */
177
181
  deleteElements(elementIds: ReadonlySet<Id64String>): Promise<void>;
178
182
  /** Delete the specified Model from the target iModel.
@@ -1 +1 @@
1
- {"version":3,"file":"IModelImporter.d.ts","sourceRoot":"","sources":["../../src/IModelImporter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"IModelImporter.d.ts","sourceRoot":"","sources":["../../src/IModelImporter.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,16 @@ const ecschema_metadata_1 = require("@itwin/ecschema-metadata");
19
19
  const IModelTransformerError_1 = require("./IModelTransformerError");
20
20
  const ElementBulkDelete_1 = require("./ElementBulkDelete");
21
21
  const loggerCategory = TransformerLoggerCategory_1.TransformerLoggerCategory.IModelImporter;
22
+ /** Lists the first kept references for a log message. */
23
+ function formatKeptReferences(keptReferences) {
24
+ const maxListed = 10;
25
+ const listed = [...keptReferences]
26
+ .slice(0, maxListed)
27
+ .map(([elementId, referencingId]) => `${elementId} (referenced by ${referencingId})`)
28
+ .join(", ");
29
+ const unlisted = keptReferences.size - maxListed;
30
+ return unlisted > 0 ? `${listed}, and ${unlisted} more` : listed;
31
+ }
22
32
  /** Base class for importing data into an iModel.
23
33
  * @see [iModel Transformation and Data Exchange]($docs/learning/transformer/index.md)
24
34
  * @see [IModelExporter]($transformer)
@@ -339,14 +349,28 @@ class IModelImporter {
339
349
  async deleteElement(elementId) {
340
350
  await this.deleteElements(new Set([elementId]));
341
351
  }
342
- /** Adds roots required by code-scope dependencies, then deletes the target element trees in one native operation.
352
+ /** Adds roots required by code-scope dependencies, then deletes the target element trees in as few native operations as their references allow.
353
+ * Usually one native operation is enough. When a tree contains a definition, such as a category, that another deleted element uses, the elements that use it are deleted first.
354
+ * Elements that something outside the deleted trees still references are kept, with a warning, and the rest are deleted.
343
355
  * @note An override must call `super.onDeleteElements` once to perform the deletion.
344
356
  */
345
357
  async onDeleteElements(elementIds) {
346
- const deleteRoots = await (0, ElementBulkDelete_1.findBulkDeleteRoots)(this.targetDb, elementIds);
347
- if (deleteRoots.size === 0)
358
+ const plan = await (0, ElementBulkDelete_1.planBulkDelete)(this.targetDb, elementIds);
359
+ if (plan.keptReferences.size > 0) {
360
+ core_bentley_1.Logger.logWarning(loggerCategory, `Kept ${plan.keptReferences.size} elements that elements outside the deleted trees still reference, and the elements that contain them: ${formatKeptReferences(plan.keptReferences)}`);
361
+ }
362
+ if (plan.phases.length === 0)
348
363
  return;
349
- const result = this._editTxn.deleteElements([...deleteRoots]);
364
+ let rootCount = 0;
365
+ for (const roots of plan.phases) {
366
+ rootCount += roots.length;
367
+ this.deleteElementRoots(roots);
368
+ }
369
+ core_bentley_1.Logger.logInfo(loggerCategory, `Deleted ${elementIds.size} requested element trees using ${rootCount} native deletion roots in ${plan.phases.length} native operations`);
370
+ await this.trackProgress(elementIds.size);
371
+ }
372
+ deleteElementRoots(roots) {
373
+ const result = this._editTxn.deleteElements(roots);
350
374
  if (result.status !== core_backend_1.BulkDeleteElementsStatus.Success) {
351
375
  core_bentley_1.ITwinError.throwError({
352
376
  iTwinErrorId: {
@@ -362,12 +386,11 @@ class IModelImporter {
362
386
  failedIds: new Set(result.failedIds),
363
387
  });
364
388
  }
365
- core_bentley_1.Logger.logInfo(loggerCategory, `Deleted ${elementIds.size} requested element trees using ${deleteRoots.size} native deletion roots`);
366
- await this.trackProgress(elementIds.size);
367
389
  }
368
- /** Deletes target element trees in one native operation.
390
+ /** Deletes target element trees, using one native operation unless references between the trees require more.
369
391
  * Requested roots in [[doNotUpdateElementIds]] are skipped. This does not prevent an element in that set from being deleted as part of another root's cascade.
370
- * @throws [[ElementBulkDeleteError]] if native deletion fails for any root. A partial failure leaves successful deletions pending in the caller-owned transaction. Abandon the transaction before retrying.
392
+ * Elements that something outside the deleted trees still references are kept, along with their child elements and sub-models and the elements that contain them. A warning lists them.
393
+ * @throws [[ElementBulkDeleteError]] if a native operation fails for any root, for example because geometry outside the deleted trees uses a geometry part in them, or because of a reference in a domain schema. The transformer does not check those references first. Deletions from that and earlier native operations stay pending in the caller-owned transaction. Abandon the transaction before retrying.
371
394
  */
372
395
  async deleteElements(elementIds) {
373
396
  const idsToDelete = new Set();
@@ -1 +1 @@
1
- {"version":3,"file":"IModelImporter.js","sourceRoot":"","sources":["../../src/IModelImporter.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module iModels\n */\nimport {\n DbResult,\n Guid,\n Id64,\n Id64String,\n IModelStatus,\n ITwinError,\n Logger,\n} from \"@itwin/core-bentley\";\nimport {\n Base64EncodedString,\n ConcreteEntityTypes,\n ECJsNames,\n ElementAspectProps,\n ElementProps,\n EntityProps,\n IModel,\n IModelError,\n ModelProps,\n RelatedElement,\n SubCategoryProps,\n} from \"@itwin/core-common\";\nimport { TransformerLoggerCategory } from \"./TransformerLoggerCategory\";\nimport {\n BulkDeleteElementsStatus,\n EditTxn,\n ElementAspect,\n ElementMultiAspect,\n Entity,\n EntityReferences,\n IModelDb,\n Relationship,\n RelationshipProps,\n SourceAndTarget,\n SubCategory,\n} from \"@itwin/core-backend\";\nimport type { RelationshipPropsForDelete } from \"./IModelTransformer\";\nimport { strict as assert } from \"node:assert\";\nimport { ElementAspectCleanup } from \"./ElementAspectCleanup\";\nimport {\n EntityClass,\n PropertyType,\n RelationshipClass,\n} from \"@itwin/ecschema-metadata\";\nimport {\n IModelTransformerError,\n IModelTransformerErrorScope,\n} from \"./IModelTransformerError\";\nimport { findBulkDeleteRoots } from \"./ElementBulkDelete\";\nimport { EntityExistenceCache } from \"./EntityExistenceCache\";\n\nconst loggerCategory: string = TransformerLoggerCategory.IModelImporter;\n\n/** Error thrown when native bulk deletion fails to delete one or more requested element trees.\n * @beta\n */\nexport interface ElementBulkDeleteError extends ITwinError {\n /** Status returned by the native bulk-delete operation. */\n readonly status: BulkDeleteElementsStatus;\n /** SQLite status returned by the native delete statement. */\n readonly sqlDeleteStatus: DbResult;\n /** Target roots that the native operation did not delete. */\n readonly failedIds: ReadonlySet<Id64String>;\n}\n\n/** Options provided to [[IModelImporter.optimizeGeometry]] specifying post-processing optimizations to be applied to the iModel's geometry.\n * @beta\n */\nexport interface OptimizeGeometryOptions {\n /** If true, identify any [GeometryPart]($backend)s that are referenced exactly once. For each such part,\n * replace the reference in the element's geometry stream with the part's own geometry stream, then delete the part.\n */\n inlineUniqueGeometryParts?: boolean;\n}\n\n/** Options provided to the [[IModelImporter]] constructor.\n * @beta\n */\nexport interface IModelImportOptions {\n /** If `true` (the default), compute the projectExtents of the target iModel after elements are imported.\n * The computed projectExtents will either include or exclude *outliers* depending on the `excludeOutliers` flag that defaults to `false`.\n * @see [[IModelImporter.autoExtendProjectExtents]]\n * @see [IModelImporter Options]($docs/learning/transformer/index.md#IModelImporter)\n */\n autoExtendProjectExtents?: boolean | { excludeOutliers: boolean };\n /** See [IModelTransformOptions]($transformer) */\n preserveElementIdsForFiltering?: boolean;\n /** If `true`, simplify the element geometry for visualization purposes. For example, convert b-reps into meshes.\n * @default false\n */\n simplifyElementGeometry?: boolean;\n /**\n * Skip propagating changes made to the root subject, dictionaryModel and IModelImporter._realityDataSourceLinkPartitionStaticId (0xe)\n * If it is set to false, changes to root elements are propagated, the root subject name gets changed and leads to the iModelDb.name property being updated in .initializeiModelDb\n * @default true\n */\n skipPropagateChangesToRootElements?: boolean;\n}\n\n/** Base class for importing data into an iModel.\n * @see [iModel Transformation and Data Exchange]($docs/learning/transformer/index.md)\n * @see [IModelExporter]($transformer)\n * @see [IModelTransformer]($transformer)\n * @beta\n */\nexport class IModelImporter {\n /** The read/write target iModel. */\n public readonly targetDb: IModelDb;\n\n /** The [[EditTxn]] used for write operations on the target iModel.\n * @beta\n */\n protected readonly _editTxn: EditTxn;\n\n /** The [[EditTxn]] used for write operations on the target iModel.\n * @beta\n */\n public get editTxn(): EditTxn {\n return this._editTxn;\n }\n\n private readonly _elementAspectCleanup: ElementAspectCleanup;\n\n /** Deletes replaceable ElementAspects through this importer's customized deletion callback.\n * @internal\n */\n public get elementAspectCleanup(): ElementAspectCleanup {\n return this._elementAspectCleanup;\n }\n\n /** resolved initialization options for the importer\n * @beta\n */\n public readonly options: Required<IModelImportOptions>;\n\n private static _realityDataSourceLinkPartitionStaticId: Id64String = \"0xe\";\n\n /**\n * A map of conflicting element code values.\n * In cases where updating an element's code value results in a codeValue conflict, the element's code value will instead be updated to a random guid.\n * The actual codeValue will be stored in this ElementId->CodeValue map.\n * This is needed in cases where the duplicate target element is set to be deleted in the future, or when elements are switching code values with one another and we need a temporary code value.\n * To resolve code values to their intended values call [[IModelImporter.resolveDuplicateCodeValues]].\n */\n private _duplicateCodeValueMap: Map<Id64String, string>;\n private readonly _entityExistenceCaches = new Set<EntityExistenceCache>();\n /**\n * A set of elementIds that the transformer adds to while exporting elements to indicate that the element already exists in the target.\n * Defaults to an empty set.\n * @note\n *\n * This is used as an optimization when `[[IModelTransformOptions.preserveElementIdsForFiltering]]` is set to `true`\n * In normal cases where this option set to `false`,\n * the importer determines whether to insert or update based off of whether the ID is defined on the `elementProps` passed to `importElement`.\n * However, with `preserveElementIdsForFiltering` set to `true`, IDs are always set, so we can't determine insert/update like the normal case.\n * The transformer already knows if an element exists or not by the time `importElement` is called and pushes to this set with `markElementToUpdateForPreserveId`.\n * @note This set should stay small, as right after the transformer pushes to it, the importer will remove from the set.\n */\n private _elementsToUpdateDuringPreserveIds = new Set<Id64String>([]);\n\n /** The set of target elements that this importer must not directly update or request for deletion.\n * Defaults to an empty set and is populated by consumers or custom transformers.\n * @note Adding an element to this set is typically necessary when remapping a source element to one that already exists in the target and already has the desired properties.\n * @note Deletion protection applies only when the exact element ID is passed to [[deleteElement]] or [[deleteElements]]. It does not protect the element from deletion through a parent, containing model, or other cascading dependency. Consumers that need to preserve such an element must also add every requested deletion root whose cascade would delete it.\n */\n public readonly doNotUpdateElementIds = new Set<Id64String>([]);\n\n /** This set is ONLY used for elements that are always present even in an \"empty\" iModel. We will use this set to filter out changes to root elements if [[IModelTransformOptions.skipPropagateChangesToRootElements]] is false. */\n private readonly _rootElementIds = new Set<Id64String>([\n IModel.rootSubjectId,\n IModel.dictionaryId,\n IModelImporter._realityDataSourceLinkPartitionStaticId,\n ]);\n\n /** The number of entity changes before incremental progress should be reported via the [[onProgress]] callback. */\n public progressInterval: number = 1000;\n /** Tracks the current total number of entity changes. */\n private _progressCounter: number = 0;\n /** */\n private _modelPropertiesToIgnore = new Set<string>([\n \"geometryGuid\", // cannot compare GeometricModel.GeometryGuid values across iModels\n ]);\n\n /** Construct a new IModelImporter\n * @param editTxn The [[EditTxn]] to use for write operations on the target iModel. The target db is derived from `editTxn.iModel`.\n * @param options The options that specify how the import should be done.\n */\n public constructor(editTxn: EditTxn, options?: IModelImportOptions) {\n this.targetDb = editTxn.iModel;\n this._editTxn = editTxn;\n this.options = {\n autoExtendProjectExtents: options?.autoExtendProjectExtents ?? true,\n preserveElementIdsForFiltering:\n options?.preserveElementIdsForFiltering ?? false,\n simplifyElementGeometry: options?.simplifyElementGeometry ?? false,\n skipPropagateChangesToRootElements:\n options?.skipPropagateChangesToRootElements ?? true,\n };\n this._duplicateCodeValueMap = new Map<Id64String, string>();\n this._elementAspectCleanup = new ElementAspectCleanup(\n this.targetDb,\n this._editTxn,\n async (aspect) => this.onDeleteElementAspect(aspect)\n );\n }\n\n /** Register a transformation-scoped existence cache for delete invalidation.\n * @internal\n */\n public registerEntityExistenceCache(cache: EntityExistenceCache): void {\n this._entityExistenceCaches.add(cache);\n }\n\n /** Stop invalidating a transformation-scoped existence cache.\n * @internal\n */\n public unregisterEntityExistenceCache(cache: EntityExistenceCache): void {\n this._entityExistenceCaches.delete(cache);\n }\n\n /**\n * Checks [[IModelImportOptions.skipPropagateChangesToRootElements]], [[IModelImporter.rootElementIds]], and [[IModelImporter.doNotUpdateElementIds]] and returns true for 'do not update', false for do 'update'.\n */\n private doNotUpdateElement(elementId: Id64String): boolean {\n if (\n this.options.skipPropagateChangesToRootElements &&\n this._rootElementIds.has(elementId)\n )\n return true;\n if (this.doNotUpdateElementIds.has(elementId)) return true;\n return false;\n }\n\n /**\n * Marks an element so that it can be updated during import when [[IModelTransformOptions.preserveElementIdsForFiltering]] is set to true.\n */\n public markElementToUpdateDuringPreserveIds(elementId: Id64String) {\n if (this._rootElementIds.has(elementId)) {\n return;\n }\n this._elementsToUpdateDuringPreserveIds.add(elementId);\n }\n\n /** Import the specified ModelProps (either as an insert or an update) into the target iModel. */\n public async importModel(modelProps: ModelProps): Promise<void> {\n if (undefined === modelProps.id || !Id64.isValidId64(modelProps.id))\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.InvalidModelId,\n },\n message:\n \"Model Id not provided, should be the same as the ModeledElementId\",\n });\n\n if (this.doNotUpdateElement(modelProps.id)) {\n Logger.logInfo(\n loggerCategory,\n `Do not update target model ${modelProps.id}`\n );\n return;\n }\n try {\n const model = this.targetDb.models.getModel(modelProps.id); // throws IModelError.NotFound if model does not exist\n if (hasEntityChanged(model, modelProps, this._modelPropertiesToIgnore)) {\n await this.onUpdateModel(modelProps);\n }\n } catch (error) {\n // catch NotFound error and insertModel\n if (\n error instanceof IModelError &&\n error.errorNumber === IModelStatus.NotFound\n ) {\n await this.onInsertModel(modelProps);\n return;\n }\n throw error;\n }\n }\n\n /** Create a new Model from the specified ModelProps and insert it into the target iModel.\n * @note A subclass may override this method to customize insert behavior but should call `super.onInsertModel`.\n */\n protected async onInsertModel(modelProps: ModelProps): Promise<Id64String> {\n try {\n const modelId: Id64String = this._editTxn.insertModel(modelProps);\n Logger.logInfo(\n loggerCategory,\n `Inserted ${this.formatModelForLogger(modelProps)}`\n );\n await this.trackProgress();\n return modelId;\n } catch (error) {\n if (!this.targetDb.containsClass(modelProps.classFullName)) {\n // Translate only confirmed missing-class failures; otherwise retain the backend error's identity.\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.TargetClassNotFound,\n },\n message: `Model class \"${modelProps.classFullName}\" not found in the target iModel. Was the latest version of the schema imported?`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n /** Update an existing Model in the target iModel from the specified ModelProps.\n * @note A subclass may override this method to customize update behavior but should call `super.onUpdateModel`.\n */\n protected async onUpdateModel(modelProps: ModelProps): Promise<void> {\n this._editTxn.updateModel(modelProps);\n Logger.logInfo(\n loggerCategory,\n `Updated ${this.formatModelForLogger(modelProps)}`\n );\n await this.trackProgress();\n }\n\n /** Format a Model for the Logger. */\n private formatModelForLogger(modelProps: ModelProps): string {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return `${modelProps.classFullName} [${modelProps.id!}]`;\n }\n\n /**\n * Tries to update an element with the specified element properties.\n * If a duplicate code error occurs, it assigns a new unique code value and retries the update\n */\n private async tryUpdateElement(elemProps: ElementProps) {\n try {\n await this.onUpdateElement(elemProps);\n } catch (err) {\n if ((err as IModelError).errorNumber === IModelStatus.DuplicateCode) {\n assert(\n elemProps.code.value !== undefined,\n \"NULL code values are always considered unique and cannot clash\"\n );\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this._duplicateCodeValueMap.set(elemProps.id!, elemProps.code.value);\n // Using NULL code values as an alternative is not valid because definition elements cannot have NULL code values.\n elemProps.code.value = Guid.createValue();\n await this.onUpdateElement(elemProps);\n } else {\n throw err;\n }\n }\n }\n\n /** Import the specified ElementProps (either as an insert or an update) into the target iModel. */\n public async importElement(elementProps: ElementProps): Promise<Id64String> {\n if (\n undefined !== elementProps.id &&\n this.doNotUpdateElement(elementProps.id)\n ) {\n Logger.logInfo(\n loggerCategory,\n `Do not update target element ${elementProps.id}`\n );\n return elementProps.id;\n }\n\n if (this.options.preserveElementIdsForFiltering) {\n if (elementProps.id === undefined) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.ElementIdRequired,\n },\n message:\n \"elementProps.id must be defined during a preserveIds operation\",\n });\n }\n\n // Categories are the only element that onInserted will immediately insert a new element (their default subcategory)\n // since default subcategories always exist and always will be inserted after their categories, we treat them as an update\n // to prevent duplicate inserts.\n // Always present elements (0xe, 0x1, 0x10) also will be updated to prevent duplicate inserts.\n if (\n (isSubCategory(elementProps) && isDefaultSubCategory(elementProps)) ||\n this._rootElementIds.has(elementProps.id)\n ) {\n await this.onUpdateElement(elementProps);\n } else {\n if (this._elementsToUpdateDuringPreserveIds.has(elementProps.id)) {\n await this.tryUpdateElement(elementProps);\n this._elementsToUpdateDuringPreserveIds.delete(elementProps.id);\n } else {\n await this.onInsertElement(elementProps);\n }\n }\n } else {\n if (undefined !== elementProps.id) {\n await this.tryUpdateElement(elementProps);\n } else {\n elementProps.id = await this.onInsertElement(elementProps); // targetElementProps.id assigned by insertElement\n }\n }\n return elementProps.id;\n }\n\n /** Create a new Element from the specified ElementProps and insert it into the target iModel.\n * @returns The Id of the newly inserted Element.\n * @note A subclass may override this method to customize insert behavior but should call `super.onInsertElement`.\n */\n protected async onInsertElement(\n elementProps: ElementProps\n ): Promise<Id64String> {\n try {\n const elementId = this._editTxn.insertElement(elementProps, {\n forceUseId: this.options.preserveElementIdsForFiltering,\n });\n // set the id like [IModelDb.insertElement]($backend), does, the raw nativeDb method does not\n elementProps.id = elementId;\n Logger.logInfo(\n loggerCategory,\n `Inserted ${this.formatElementForLogger(elementProps)}`\n );\n await this.trackProgress();\n if (this.options.simplifyElementGeometry) {\n this.targetDb.simplifyElementGeometry({\n id: elementId,\n convertBReps: true,\n });\n Logger.logInfo(\n loggerCategory,\n `Simplified element geometry for ${this.formatElementForLogger(\n elementProps\n )}`\n );\n }\n return elementId;\n } catch (error) {\n if (!this.targetDb.containsClass(elementProps.classFullName)) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.TargetClassNotFound,\n },\n message: `Element class \"${elementProps.classFullName}\" not found in the target iModel. Was the latest version of the schema imported?`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n /** Update an existing Element in the target iModel from the specified ElementProps.\n * @note A subclass may override this method to customize update behavior but should call `super.onUpdateElement`.\n */\n protected async onUpdateElement(elementProps: ElementProps): Promise<void> {\n if (!elementProps.id) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.ElementIdRequired,\n },\n message: \"ElementId not provided\",\n });\n }\n this._editTxn.updateElement(elementProps);\n Logger.logInfo(\n loggerCategory,\n `Updated ${this.formatElementForLogger(elementProps)}`\n );\n await this.trackProgress();\n if (this.options.simplifyElementGeometry) {\n this.targetDb.simplifyElementGeometry({\n id: elementProps.id,\n convertBReps: true,\n });\n Logger.logInfo(\n loggerCategory,\n `Simplified element geometry for ${this.formatElementForLogger(\n elementProps\n )}`\n );\n }\n }\n\n /** Deletes one target element tree through [[deleteElements]]. */\n public async deleteElement(elementId: Id64String): Promise<void> {\n await this.deleteElements(new Set([elementId]));\n }\n\n /** Adds roots required by code-scope dependencies, then deletes the target element trees in one native operation.\n * @note An override must call `super.onDeleteElements` once to perform the deletion.\n */\n protected async onDeleteElements(\n elementIds: ReadonlySet<Id64String>\n ): Promise<void> {\n const deleteRoots = await findBulkDeleteRoots(this.targetDb, elementIds);\n if (deleteRoots.size === 0) return;\n const result = this._editTxn.deleteElements([...deleteRoots]);\n if (result.status !== BulkDeleteElementsStatus.Success) {\n ITwinError.throwError<ElementBulkDeleteError>({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.ElementBulkDeleteFailed,\n },\n message:\n `Bulk element deletion failed: status ${BulkDeleteElementsStatus[result.status]}, ` +\n `SQLite status ${result.sqlDeleteStatus}, failed element IDs: ${[\n ...result.failedIds,\n ].join(\", \")}`,\n status: result.status,\n sqlDeleteStatus: result.sqlDeleteStatus,\n failedIds: new Set(result.failedIds),\n });\n }\n\n Logger.logInfo(\n loggerCategory,\n `Deleted ${elementIds.size} requested element trees using ${deleteRoots.size} native deletion roots`\n );\n await this.trackProgress(elementIds.size);\n }\n\n /** Deletes target element trees in one native operation.\n * Requested roots in [[doNotUpdateElementIds]] are skipped. This does not prevent an element in that set from being deleted as part of another root's cascade.\n * @throws [[ElementBulkDeleteError]] if native deletion fails for any root. A partial failure leaves successful deletions pending in the caller-owned transaction. Abandon the transaction before retrying.\n */\n public async deleteElements(\n elementIds: ReadonlySet<Id64String>\n ): Promise<void> {\n const idsToDelete = new Set<Id64String>();\n for (const elementId of elementIds) {\n if (!this.doNotUpdateElement(elementId)) {\n idsToDelete.add(elementId);\n continue;\n }\n Logger.logInfo(\n loggerCategory,\n `Do not delete target element ${elementId}`\n );\n }\n if (idsToDelete.size === 0) return;\n await this.onDeleteElements(idsToDelete);\n // Element deletion cascades can remove descendants and their submodels.\n for (const cache of this._entityExistenceCaches)\n cache.clearDb(this.targetDb);\n }\n\n /** Delete the specified Model from the target iModel.\n * @note A subclass may override this method to customize delete behavior but should call `super.onDeleteModel`.\n */\n protected async onDeleteModel(modelId: Id64String): Promise<void> {\n this._editTxn.deleteModel(modelId);\n Logger.logInfo(loggerCategory, `Deleted model ${modelId}`);\n await this.trackProgress();\n }\n\n /** Delete the specified Model from the target iModel. */\n public async deleteModel(modelId: Id64String): Promise<void> {\n await this.onDeleteModel(modelId);\n const modelReference = EntityReferences.fromEntityType(\n modelId,\n ConcreteEntityTypes.Model\n );\n for (const cache of this._entityExistenceCaches)\n cache.invalidate(this.targetDb, modelReference);\n }\n\n /** Format an Element for the Logger. */\n private formatElementForLogger(elementProps: ElementProps): string {\n const namePiece: string = elementProps.code.value\n ? `${elementProps.code.value} `\n : elementProps.userLabel\n ? `${elementProps.userLabel} `\n : \"\";\n return `${elementProps.classFullName} ${namePiece}[${elementProps.id}]`;\n }\n\n /** Import an ElementUniqueAspect into the target iModel. */\n public async importElementUniqueAspect(\n aspectProps: ElementAspectProps\n ): Promise<Id64String> {\n const aspects: ElementAspect[] = this.targetDb.elements.getAspects(\n aspectProps.element.id,\n aspectProps.classFullName\n );\n if (aspects.length === 0) {\n return this.onInsertElementAspect(aspectProps);\n } else if (hasEntityChanged(aspects[0], aspectProps)) {\n aspectProps.id = aspects[0].id;\n await this.onUpdateElementAspect(aspectProps);\n }\n return aspects[0].id;\n }\n\n /** Import the collection of ElementMultiAspects into the target iModel.\n * @param aspectPropsArray The ElementMultiAspects to import\n * @param filterFunc Optional filter func that is used to exclude target ElementMultiAspects that were added during iModel transformation from the update detection logic.\n * @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.\n * @returns the array of ids of the resulting ElementMultiAspects, in the same order of the aspectPropsArray parameter\n */\n public async importElementMultiAspects(\n aspectPropsArray: ElementAspectProps[],\n /** caller must use this to enforce any aspects added by IModelTransformer are not considered for update */\n filterFunc: (a: ElementMultiAspect) => boolean = () => true\n ): Promise<Id64String[]> {\n const result = new Array<Id64String | undefined>(\n aspectPropsArray.length\n ).fill(undefined);\n\n if (aspectPropsArray.length === 0) {\n return result as Id64String[];\n }\n\n const elementId: Id64String = aspectPropsArray[0].element.id;\n const proposedAspectsByClass = new Map<\n string,\n Array<{ props: ElementAspectProps; index: number }>\n >();\n aspectPropsArray.forEach((props, index): void => {\n const proposedAspects =\n proposedAspectsByClass.get(props.classFullName) ?? [];\n proposedAspects.push({ props, index });\n proposedAspectsByClass.set(props.classFullName, proposedAspects);\n });\n\n // Handle ElementMultiAspects in groups by class\n for (const [\n aspectClassFullName,\n proposedAspects,\n ] of proposedAspectsByClass) {\n const currentAspects = this.targetDb.elements\n .getAspects(elementId, aspectClassFullName)\n .map((props, index) => ({ props, index }) as const)\n .filter(({ props }) => filterFunc(props));\n\n if (proposedAspects.length >= currentAspects.length) {\n for (let index = 0; index < proposedAspects.length; index++) {\n const { props, index: resultIndex } = proposedAspects[index];\n let id: Id64String;\n if (index < currentAspects.length) {\n id = currentAspects[index].props.id;\n props.id = id;\n if (hasEntityChanged(currentAspects[index].props, props)) {\n await this.onUpdateElementAspect(props);\n }\n id = props.id;\n } else {\n id = await this.onInsertElementAspect(props);\n }\n result[resultIndex] = id;\n }\n } else {\n for (let index = 0; index < currentAspects.length; index++) {\n const { props } = currentAspects[index];\n if (index < proposedAspects.length) {\n const { props: proposedProps, index: resultIndex } =\n proposedAspects[index];\n const id = props.id;\n proposedProps.id = id;\n if (hasEntityChanged(props, proposedProps)) {\n await this.onUpdateElementAspect(proposedProps);\n }\n result[resultIndex] = id;\n } else {\n await this.onDeleteElementAspect(props);\n }\n }\n }\n }\n\n assert(result.every((r) => r !== undefined));\n return result;\n }\n\n /** Insert the ElementAspect into the target iModel.\n * @note A subclass may override this method to customize insert behavior but should call `super.onInsertElementAspect`.\n */\n protected async onInsertElementAspect(\n aspectProps: ElementAspectProps\n ): Promise<Id64String> {\n try {\n const id = this._editTxn.insertAspect(aspectProps);\n Logger.logInfo(\n loggerCategory,\n `Inserted ${this.formatElementAspectForLogger(aspectProps)}`\n );\n await this.trackProgress();\n return id;\n } catch (error) {\n if (!this.targetDb.containsClass(aspectProps.classFullName)) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.TargetClassNotFound,\n },\n message: `ElementAspect class \"${aspectProps.classFullName}\" not found in the target iModel. Was the latest version of the schema imported?`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n /** Update the ElementAspect within the target iModel.\n * @note A subclass may override this method to customize update behavior but should call `super.onUpdateElementAspect`.\n */\n protected async onUpdateElementAspect(\n aspectProps: ElementAspectProps\n ): Promise<void> {\n this._editTxn.updateAspect(aspectProps);\n Logger.logInfo(\n loggerCategory,\n `Updated ${this.formatElementAspectForLogger(aspectProps)}`\n );\n await this.trackProgress();\n }\n\n /** Delete the specified ElementAspect from the target iModel.\n * @note A subclass may override this method to customize delete behavior but should call `super.onDeleteElementAspect`.\n */\n protected async onDeleteElementAspect(\n targetElementAspect: ElementAspect\n ): Promise<void> {\n this._editTxn.deleteAspect(targetElementAspect.id);\n Logger.logInfo(\n loggerCategory,\n `Deleted ${this.formatElementAspectForLogger(targetElementAspect)}`\n );\n await this.trackProgress();\n }\n\n /** Format an ElementAspect for the Logger. */\n private formatElementAspectForLogger(\n elementAspectProps: ElementAspectProps | ElementAspect\n ): string {\n return `${elementAspectProps.classFullName} elementId=[${elementAspectProps.element.id}]`;\n }\n\n /** Import the specified RelationshipProps (either as an insert or an update) into the target iModel.\n * @returns The instance Id of the inserted or updated Relationship.\n */\n public async importRelationship(\n relationshipProps: RelationshipProps\n ): Promise<Id64String> {\n if (\n undefined === relationshipProps.sourceId ||\n !Id64.isValidId64(relationshipProps.sourceId)\n ) {\n Logger.logInfo(\n loggerCategory,\n `Ignoring ${relationshipProps.classFullName} instance because of invalid RelationshipProps.sourceId`\n );\n return Id64.invalid;\n }\n if (\n undefined === relationshipProps.targetId ||\n !Id64.isValidId64(relationshipProps.targetId)\n ) {\n Logger.logInfo(\n loggerCategory,\n `Ignoring ${relationshipProps.classFullName} instance because of invalid RelationshipProps.targetId`\n );\n return Id64.invalid;\n }\n // check for an existing relationship\n const relSourceAndTarget: SourceAndTarget = {\n sourceId: relationshipProps.sourceId,\n targetId: relationshipProps.targetId,\n };\n const relationship: Relationship | undefined =\n this.targetDb.relationships.tryGetInstance(\n relationshipProps.classFullName,\n relSourceAndTarget\n );\n if (undefined !== relationship) {\n // if relationship found, update it\n relationshipProps.id = relationship.id;\n if (hasEntityChanged(relationship, relationshipProps)) {\n await this.onUpdateRelationship(relationshipProps);\n }\n return relationshipProps.id;\n } else {\n return this.onInsertRelationship(relationshipProps);\n }\n }\n\n /** Create a new Relationship from the specified RelationshipProps and insert it into the target iModel.\n * @returns The instance Id of the newly inserted relationship.\n * @note A subclass may override this method to customize insert behavior but should call `super.onInsertRelationship`.\n */\n protected async onInsertRelationship(\n relationshipProps: RelationshipProps\n ): Promise<Id64String> {\n try {\n const targetRelInstanceId: Id64String =\n this._editTxn.insertRelationship(relationshipProps);\n Logger.logInfo(\n loggerCategory,\n `Inserted ${this.formatRelationshipForLogger(relationshipProps)}`\n );\n await this.trackProgress();\n return targetRelInstanceId;\n } catch (error) {\n if (!this.targetDb.containsClass(relationshipProps.classFullName)) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.TargetClassNotFound,\n },\n message: `Relationship class \"${relationshipProps.classFullName}\" not found in the target iModel. Was the latest version of the schema imported?`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n /** Update an existing Relationship in the target iModel from the specified RelationshipProps.\n * @note A subclass may override this method to customize update behavior but should call `super.onUpdateRelationship`.\n */\n protected async onUpdateRelationship(\n relationshipProps: RelationshipProps\n ): Promise<void> {\n if (!relationshipProps.id) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.RelationshipIdRequired,\n },\n message: \"Relationship instance Id not provided\",\n });\n }\n this._editTxn.updateRelationship(relationshipProps);\n Logger.logInfo(\n loggerCategory,\n `Updated ${this.formatRelationshipForLogger(relationshipProps)}`\n );\n await this.trackProgress();\n }\n\n /** Delete the specified Relationship from the target iModel. */\n protected async onDeleteRelationship(\n relationshipProps: RelationshipPropsForDelete\n ): Promise<void> {\n // Only passing in what deleteInstance actually uses, full relationshipProps is not necessary.\n this._editTxn.deleteRelationship({\n id: relationshipProps.id,\n classFullName: relationshipProps.classFullName,\n } as RelationshipProps);\n Logger.logInfo(\n loggerCategory,\n `Deleted relationship ${relationshipProps.classFullName} id=${relationshipProps.id}`\n );\n await this.trackProgress();\n }\n\n /** Delete the specified Relationship from the target iModel. */\n public async deleteRelationship(\n relationshipProps: RelationshipPropsForDelete\n ): Promise<void> {\n await this.onDeleteRelationship(relationshipProps);\n }\n\n /** Format a Relationship for the Logger. */\n private formatRelationshipForLogger(relProps: RelationshipProps): string {\n return `${relProps.classFullName} sourceId=[${relProps.sourceId}] targetId=[${relProps.targetId}]`;\n }\n\n /** Tracks incremental progress */\n private async trackProgress(increment = 1): Promise<void> {\n const previousProgressCounter = this._progressCounter;\n this._progressCounter += increment;\n const progressCallbacks =\n Math.floor(this._progressCounter / this.progressInterval) -\n Math.floor(previousProgressCounter / this.progressInterval);\n for (let i = 0; i < progressCallbacks; ++i) await this.onProgress();\n }\n\n /** This method is called when IModelImporter has made incremental progress based on the [[progressInterval]] setting.\n * @note A subclass may override this method to report custom progress but should call `super.onProgress`.\n */\n protected async onProgress(): Promise<void> {}\n\n /** Optionally compute the projectExtents for the target iModel depending on the options for this IModelImporter.\n * @note This method is automatically called from [IModelTransformer.process]($transformer).\n * @see [IModelDb.computeProjectExtents]($backend), [[autoExtendProjectExtents]]\n */\n public computeProjectExtents(): void {\n const computedProjectExtents = this.targetDb.computeProjectExtents({\n reportExtentsWithOutliers: true,\n reportOutliers: true,\n });\n Logger.logInfo(\n loggerCategory,\n `Current projectExtents=${JSON.stringify(this.targetDb.projectExtents)}`\n );\n Logger.logInfo(\n loggerCategory,\n `Computed projectExtents without outliers=${JSON.stringify(\n computedProjectExtents.extents\n )}`\n );\n Logger.logInfo(\n loggerCategory,\n `Computed projectExtents with outliers=${JSON.stringify(\n computedProjectExtents.extentsWithOutliers\n )}`\n );\n if (this.options.autoExtendProjectExtents) {\n const excludeOutliers: boolean =\n typeof this.options.autoExtendProjectExtents === \"object\"\n ? this.options.autoExtendProjectExtents.excludeOutliers\n : false;\n // If excludeOutliers is true, use the extents without outliers.\n // Otherwise prefer extentsWithOutliers, but fall back to extents if it's undefined or a null range.\n const extentsWithOutliers = computedProjectExtents.extentsWithOutliers;\n const useExtentsWithOutliers =\n !excludeOutliers && extentsWithOutliers && !extentsWithOutliers.isNull;\n const newProjectExtents = useExtentsWithOutliers\n ? extentsWithOutliers\n : computedProjectExtents.extents;\n if (!newProjectExtents.isAlmostEqual(this.targetDb.projectExtents)) {\n this._editTxn.updateProjectExtents(newProjectExtents);\n Logger.logInfo(\n loggerCategory,\n `Updated projectExtents=${JSON.stringify(\n this.targetDb.projectExtents\n )}`\n );\n }\n if (\n !excludeOutliers &&\n computedProjectExtents.outliers &&\n computedProjectExtents.outliers.length > 0\n ) {\n Logger.logInfo(\n loggerCategory,\n `${computedProjectExtents.outliers.length} outliers detected within projectExtents`\n );\n }\n } else {\n if (\n !this.targetDb.projectExtents.containsRange(\n computedProjectExtents.extents\n )\n ) {\n Logger.logWarning(\n loggerCategory,\n \"Current project extents may be too small\"\n );\n }\n if (\n computedProjectExtents.outliers &&\n computedProjectExtents.outliers.length > 0\n ) {\n Logger.logInfo(\n loggerCategory,\n `${computedProjectExtents.outliers.length} outliers detected within projectExtents`\n );\n }\n }\n }\n\n /** Examine the geometry streams of every [GeometricElement3d]($backend) in the target iModel and apply the specified optimizations.\n * @note This method is automatically called from [[IModelTransformer.process]] if\n * [[IModelTransformOptions.optimizeGeometry]] is defined.\n */\n public optimizeGeometry(options: OptimizeGeometryOptions): void {\n if (options.inlineUniqueGeometryParts) {\n const result = this.targetDb.inlineGeometryParts();\n Logger.logInfo(\n loggerCategory,\n `Inlined ${result.numRefsInlined} references to ${result.numCandidateParts} geometry parts and deleted ${result.numPartsDeleted} parts.`\n );\n }\n }\n\n private resolveDuplicateCodeValues(): void {\n for (const [elementId, codeValue] of this._duplicateCodeValueMap) {\n const element = this.targetDb.elements.getElement(elementId);\n element.code.value = codeValue;\n this._editTxn.updateElement(element.toJSON());\n }\n this._duplicateCodeValueMap.clear();\n }\n\n /**\n * Needs to be called to perform necessary cleanup operations.\n * By not calling `finalize` there is a risk that data imported into targetDb will not be as expected.\n *\n * @note [[IModelTransformer.process]] invokes this method automatically. Call it explicitly after\n * composing the transformer's lower-level subset processing methods.\n */\n public finalize(): void {\n this.resolveDuplicateCodeValues();\n }\n}\n\n/** Returns true if a change within an Entity is detected.\n * @param entity The current persistent Entity.\n * @param entityProps The new EntityProps to compare against\n * @note This method should only be called if changeset information is not available.\n * @internal\n */\nexport function hasEntityChanged(\n entity: Entity,\n entityProps: EntityProps,\n namesToIgnore?: Set<string>\n): boolean {\n let changed: boolean = false;\n const entityClass = entity.iModel.schemaContext.getSchemaItemSync(\n entity.schemaItemKey\n );\n assert(\n EntityClass.isEntityClass(entityClass) ||\n RelationshipClass.isRelationshipClass(entityClass),\n `Cannot get metadata for ${entity.classFullName}.`\n );\n for (const property of entityClass.getPropertiesSync()) {\n const propertyName = property.name;\n if (!changed) {\n if (namesToIgnore && namesToIgnore.has(propertyName)) {\n // skip\n } else if (PropertyType.Binary === property.propertyType) {\n changed = hasBinaryValueChanged(\n entity.asAny[ECJsNames.toJsName(propertyName)],\n (entityProps as any)[ECJsNames.toJsName(propertyName)]\n );\n } else if (property.isNavigation()) {\n changed = hasNavigationValueChanged(\n entity.asAny[ECJsNames.toJsName(propertyName)],\n (entityProps as any)[ECJsNames.toJsName(propertyName)]\n );\n } else {\n changed = hasValueChanged(\n entity.asAny[ECJsNames.toJsName(propertyName)],\n (entityProps as any)[ECJsNames.toJsName(propertyName)]\n );\n }\n }\n }\n return changed;\n}\n\n/** Returns true if the specified binary values are different. */\nfunction hasBinaryValueChanged(\n binaryProperty1: any,\n binaryProperty2: any\n): boolean {\n const jsonString1 = JSON.stringify(\n binaryProperty1,\n Base64EncodedString.replacer\n );\n const jsonString2 = JSON.stringify(\n binaryProperty2,\n Base64EncodedString.replacer\n );\n return jsonString1 !== jsonString2;\n}\n\n/** Returns true if the specified navigation property values are different. */\nfunction hasNavigationValueChanged(\n navigationProperty1: any,\n navigationProperty2: any\n): boolean {\n const relatedElement1 = RelatedElement.fromJSON(navigationProperty1);\n const relatedElement2 = RelatedElement.fromJSON(navigationProperty2);\n const jsonString1 = JSON.stringify(relatedElement1);\n const jsonString2 = JSON.stringify(relatedElement2);\n return jsonString1 !== jsonString2;\n}\n\n/** Returns true if the specified navigation property values are different. */\nfunction hasValueChanged(property1: any, property2: any): boolean {\n return JSON.stringify(property1) !== JSON.stringify(property2);\n}\n\n/** check if element props are a subcategory */\nfunction isSubCategory(props: ElementProps): props is SubCategoryProps {\n return props.classFullName === SubCategory.classFullName;\n}\n\n/** check if element props are a subcategory without loading the element */\nfunction isDefaultSubCategory(props: SubCategoryProps): boolean {\n if (props.id === undefined) return false;\n\n if (!Id64.isId64(props.id))\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.InvalidSubCategory,\n },\n message: \"subcategory had invalid id\",\n });\n if (props.parent?.id === undefined)\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.InvalidSubCategory,\n },\n message: `subcategory with id ${props.id} had no parent`,\n });\n return props.id === IModelDb.getDefaultSubCategoryId(props.parent.id);\n}\n"]}
1
+ {"version":3,"file":"IModelImporter.js","sourceRoot":"","sources":["../../src/IModelImporter.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module iModels\n */\nimport {\n DbResult,\n Guid,\n Id64,\n Id64String,\n IModelStatus,\n ITwinError,\n Logger,\n} from \"@itwin/core-bentley\";\nimport {\n Base64EncodedString,\n ConcreteEntityTypes,\n ECJsNames,\n ElementAspectProps,\n ElementProps,\n EntityProps,\n IModel,\n IModelError,\n ModelProps,\n RelatedElement,\n SubCategoryProps,\n} from \"@itwin/core-common\";\nimport { TransformerLoggerCategory } from \"./TransformerLoggerCategory\";\nimport {\n BulkDeleteElementsStatus,\n EditTxn,\n ElementAspect,\n ElementMultiAspect,\n Entity,\n EntityReferences,\n IModelDb,\n Relationship,\n RelationshipProps,\n SourceAndTarget,\n SubCategory,\n} from \"@itwin/core-backend\";\nimport type { RelationshipPropsForDelete } from \"./IModelTransformer\";\nimport { strict as assert } from \"node:assert\";\nimport { ElementAspectCleanup } from \"./ElementAspectCleanup\";\nimport {\n EntityClass,\n PropertyType,\n RelationshipClass,\n} from \"@itwin/ecschema-metadata\";\nimport {\n IModelTransformerError,\n IModelTransformerErrorScope,\n} from \"./IModelTransformerError\";\nimport { planBulkDelete } from \"./ElementBulkDelete\";\nimport { EntityExistenceCache } from \"./EntityExistenceCache\";\n\nconst loggerCategory: string = TransformerLoggerCategory.IModelImporter;\n\n/** Lists the first kept references for a log message. */\nfunction formatKeptReferences(\n keptReferences: ReadonlyMap<Id64String, Id64String>\n): string {\n const maxListed = 10;\n const listed = [...keptReferences]\n .slice(0, maxListed)\n .map(\n ([elementId, referencingId]) =>\n `${elementId} (referenced by ${referencingId})`\n )\n .join(\", \");\n const unlisted = keptReferences.size - maxListed;\n return unlisted > 0 ? `${listed}, and ${unlisted} more` : listed;\n}\n\n/** Error thrown when native bulk deletion fails to delete one or more requested element trees.\n * @beta\n */\nexport interface ElementBulkDeleteError extends ITwinError {\n /** Status returned by the native bulk-delete operation. */\n readonly status: BulkDeleteElementsStatus;\n /** SQLite status returned by the native delete statement. */\n readonly sqlDeleteStatus: DbResult;\n /** Target roots that the native operation did not delete. */\n readonly failedIds: ReadonlySet<Id64String>;\n}\n\n/** Options provided to [[IModelImporter.optimizeGeometry]] specifying post-processing optimizations to be applied to the iModel's geometry.\n * @beta\n */\nexport interface OptimizeGeometryOptions {\n /** If true, identify any [GeometryPart]($backend)s that are referenced exactly once. For each such part,\n * replace the reference in the element's geometry stream with the part's own geometry stream, then delete the part.\n */\n inlineUniqueGeometryParts?: boolean;\n}\n\n/** Options provided to the [[IModelImporter]] constructor.\n * @beta\n */\nexport interface IModelImportOptions {\n /** If `true` (the default), compute the projectExtents of the target iModel after elements are imported.\n * The computed projectExtents will either include or exclude *outliers* depending on the `excludeOutliers` flag that defaults to `false`.\n * @see [[IModelImporter.autoExtendProjectExtents]]\n * @see [IModelImporter Options]($docs/learning/transformer/index.md#IModelImporter)\n */\n autoExtendProjectExtents?: boolean | { excludeOutliers: boolean };\n /** See [IModelTransformOptions]($transformer) */\n preserveElementIdsForFiltering?: boolean;\n /** If `true`, simplify the element geometry for visualization purposes. For example, convert b-reps into meshes.\n * @default false\n */\n simplifyElementGeometry?: boolean;\n /**\n * Skip propagating changes made to the root subject, dictionaryModel and IModelImporter._realityDataSourceLinkPartitionStaticId (0xe)\n * If it is set to false, changes to root elements are propagated, the root subject name gets changed and leads to the iModelDb.name property being updated in .initializeiModelDb\n * @default true\n */\n skipPropagateChangesToRootElements?: boolean;\n}\n\n/** Base class for importing data into an iModel.\n * @see [iModel Transformation and Data Exchange]($docs/learning/transformer/index.md)\n * @see [IModelExporter]($transformer)\n * @see [IModelTransformer]($transformer)\n * @beta\n */\nexport class IModelImporter {\n /** The read/write target iModel. */\n public readonly targetDb: IModelDb;\n\n /** The [[EditTxn]] used for write operations on the target iModel.\n * @beta\n */\n protected readonly _editTxn: EditTxn;\n\n /** The [[EditTxn]] used for write operations on the target iModel.\n * @beta\n */\n public get editTxn(): EditTxn {\n return this._editTxn;\n }\n\n private readonly _elementAspectCleanup: ElementAspectCleanup;\n\n /** Deletes replaceable ElementAspects through this importer's customized deletion callback.\n * @internal\n */\n public get elementAspectCleanup(): ElementAspectCleanup {\n return this._elementAspectCleanup;\n }\n\n /** resolved initialization options for the importer\n * @beta\n */\n public readonly options: Required<IModelImportOptions>;\n\n private static _realityDataSourceLinkPartitionStaticId: Id64String = \"0xe\";\n\n /**\n * A map of conflicting element code values.\n * In cases where updating an element's code value results in a codeValue conflict, the element's code value will instead be updated to a random guid.\n * The actual codeValue will be stored in this ElementId->CodeValue map.\n * This is needed in cases where the duplicate target element is set to be deleted in the future, or when elements are switching code values with one another and we need a temporary code value.\n * To resolve code values to their intended values call [[IModelImporter.resolveDuplicateCodeValues]].\n */\n private _duplicateCodeValueMap: Map<Id64String, string>;\n private readonly _entityExistenceCaches = new Set<EntityExistenceCache>();\n /**\n * A set of elementIds that the transformer adds to while exporting elements to indicate that the element already exists in the target.\n * Defaults to an empty set.\n * @note\n *\n * This is used as an optimization when `[[IModelTransformOptions.preserveElementIdsForFiltering]]` is set to `true`\n * In normal cases where this option set to `false`,\n * the importer determines whether to insert or update based off of whether the ID is defined on the `elementProps` passed to `importElement`.\n * However, with `preserveElementIdsForFiltering` set to `true`, IDs are always set, so we can't determine insert/update like the normal case.\n * The transformer already knows if an element exists or not by the time `importElement` is called and pushes to this set with `markElementToUpdateForPreserveId`.\n * @note This set should stay small, as right after the transformer pushes to it, the importer will remove from the set.\n */\n private _elementsToUpdateDuringPreserveIds = new Set<Id64String>([]);\n\n /** The set of target elements that this importer must not directly update or request for deletion.\n * Defaults to an empty set and is populated by consumers or custom transformers.\n * @note Adding an element to this set is typically necessary when remapping a source element to one that already exists in the target and already has the desired properties.\n * @note Deletion protection applies only when the exact element ID is passed to [[deleteElement]] or [[deleteElements]]. It does not protect the element from deletion through a parent, containing model, or other cascading dependency. Consumers that need to preserve such an element must also add every requested deletion root whose cascade would delete it.\n */\n public readonly doNotUpdateElementIds = new Set<Id64String>([]);\n\n /** This set is ONLY used for elements that are always present even in an \"empty\" iModel. We will use this set to filter out changes to root elements if [[IModelTransformOptions.skipPropagateChangesToRootElements]] is false. */\n private readonly _rootElementIds = new Set<Id64String>([\n IModel.rootSubjectId,\n IModel.dictionaryId,\n IModelImporter._realityDataSourceLinkPartitionStaticId,\n ]);\n\n /** The number of entity changes before incremental progress should be reported via the [[onProgress]] callback. */\n public progressInterval: number = 1000;\n /** Tracks the current total number of entity changes. */\n private _progressCounter: number = 0;\n /** */\n private _modelPropertiesToIgnore = new Set<string>([\n \"geometryGuid\", // cannot compare GeometricModel.GeometryGuid values across iModels\n ]);\n\n /** Construct a new IModelImporter\n * @param editTxn The [[EditTxn]] to use for write operations on the target iModel. The target db is derived from `editTxn.iModel`.\n * @param options The options that specify how the import should be done.\n */\n public constructor(editTxn: EditTxn, options?: IModelImportOptions) {\n this.targetDb = editTxn.iModel;\n this._editTxn = editTxn;\n this.options = {\n autoExtendProjectExtents: options?.autoExtendProjectExtents ?? true,\n preserveElementIdsForFiltering:\n options?.preserveElementIdsForFiltering ?? false,\n simplifyElementGeometry: options?.simplifyElementGeometry ?? false,\n skipPropagateChangesToRootElements:\n options?.skipPropagateChangesToRootElements ?? true,\n };\n this._duplicateCodeValueMap = new Map<Id64String, string>();\n this._elementAspectCleanup = new ElementAspectCleanup(\n this.targetDb,\n this._editTxn,\n async (aspect) => this.onDeleteElementAspect(aspect)\n );\n }\n\n /** Register a transformation-scoped existence cache for delete invalidation.\n * @internal\n */\n public registerEntityExistenceCache(cache: EntityExistenceCache): void {\n this._entityExistenceCaches.add(cache);\n }\n\n /** Stop invalidating a transformation-scoped existence cache.\n * @internal\n */\n public unregisterEntityExistenceCache(cache: EntityExistenceCache): void {\n this._entityExistenceCaches.delete(cache);\n }\n\n /**\n * Checks [[IModelImportOptions.skipPropagateChangesToRootElements]], [[IModelImporter.rootElementIds]], and [[IModelImporter.doNotUpdateElementIds]] and returns true for 'do not update', false for do 'update'.\n */\n private doNotUpdateElement(elementId: Id64String): boolean {\n if (\n this.options.skipPropagateChangesToRootElements &&\n this._rootElementIds.has(elementId)\n )\n return true;\n if (this.doNotUpdateElementIds.has(elementId)) return true;\n return false;\n }\n\n /**\n * Marks an element so that it can be updated during import when [[IModelTransformOptions.preserveElementIdsForFiltering]] is set to true.\n */\n public markElementToUpdateDuringPreserveIds(elementId: Id64String) {\n if (this._rootElementIds.has(elementId)) {\n return;\n }\n this._elementsToUpdateDuringPreserveIds.add(elementId);\n }\n\n /** Import the specified ModelProps (either as an insert or an update) into the target iModel. */\n public async importModel(modelProps: ModelProps): Promise<void> {\n if (undefined === modelProps.id || !Id64.isValidId64(modelProps.id))\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.InvalidModelId,\n },\n message:\n \"Model Id not provided, should be the same as the ModeledElementId\",\n });\n\n if (this.doNotUpdateElement(modelProps.id)) {\n Logger.logInfo(\n loggerCategory,\n `Do not update target model ${modelProps.id}`\n );\n return;\n }\n try {\n const model = this.targetDb.models.getModel(modelProps.id); // throws IModelError.NotFound if model does not exist\n if (hasEntityChanged(model, modelProps, this._modelPropertiesToIgnore)) {\n await this.onUpdateModel(modelProps);\n }\n } catch (error) {\n // catch NotFound error and insertModel\n if (\n error instanceof IModelError &&\n error.errorNumber === IModelStatus.NotFound\n ) {\n await this.onInsertModel(modelProps);\n return;\n }\n throw error;\n }\n }\n\n /** Create a new Model from the specified ModelProps and insert it into the target iModel.\n * @note A subclass may override this method to customize insert behavior but should call `super.onInsertModel`.\n */\n protected async onInsertModel(modelProps: ModelProps): Promise<Id64String> {\n try {\n const modelId: Id64String = this._editTxn.insertModel(modelProps);\n Logger.logInfo(\n loggerCategory,\n `Inserted ${this.formatModelForLogger(modelProps)}`\n );\n await this.trackProgress();\n return modelId;\n } catch (error) {\n if (!this.targetDb.containsClass(modelProps.classFullName)) {\n // Translate only confirmed missing-class failures; otherwise retain the backend error's identity.\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.TargetClassNotFound,\n },\n message: `Model class \"${modelProps.classFullName}\" not found in the target iModel. Was the latest version of the schema imported?`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n /** Update an existing Model in the target iModel from the specified ModelProps.\n * @note A subclass may override this method to customize update behavior but should call `super.onUpdateModel`.\n */\n protected async onUpdateModel(modelProps: ModelProps): Promise<void> {\n this._editTxn.updateModel(modelProps);\n Logger.logInfo(\n loggerCategory,\n `Updated ${this.formatModelForLogger(modelProps)}`\n );\n await this.trackProgress();\n }\n\n /** Format a Model for the Logger. */\n private formatModelForLogger(modelProps: ModelProps): string {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return `${modelProps.classFullName} [${modelProps.id!}]`;\n }\n\n /**\n * Tries to update an element with the specified element properties.\n * If a duplicate code error occurs, it assigns a new unique code value and retries the update\n */\n private async tryUpdateElement(elemProps: ElementProps) {\n try {\n await this.onUpdateElement(elemProps);\n } catch (err) {\n if ((err as IModelError).errorNumber === IModelStatus.DuplicateCode) {\n assert(\n elemProps.code.value !== undefined,\n \"NULL code values are always considered unique and cannot clash\"\n );\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this._duplicateCodeValueMap.set(elemProps.id!, elemProps.code.value);\n // Using NULL code values as an alternative is not valid because definition elements cannot have NULL code values.\n elemProps.code.value = Guid.createValue();\n await this.onUpdateElement(elemProps);\n } else {\n throw err;\n }\n }\n }\n\n /** Import the specified ElementProps (either as an insert or an update) into the target iModel. */\n public async importElement(elementProps: ElementProps): Promise<Id64String> {\n if (\n undefined !== elementProps.id &&\n this.doNotUpdateElement(elementProps.id)\n ) {\n Logger.logInfo(\n loggerCategory,\n `Do not update target element ${elementProps.id}`\n );\n return elementProps.id;\n }\n\n if (this.options.preserveElementIdsForFiltering) {\n if (elementProps.id === undefined) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.ElementIdRequired,\n },\n message:\n \"elementProps.id must be defined during a preserveIds operation\",\n });\n }\n\n // Categories are the only element that onInserted will immediately insert a new element (their default subcategory)\n // since default subcategories always exist and always will be inserted after their categories, we treat them as an update\n // to prevent duplicate inserts.\n // Always present elements (0xe, 0x1, 0x10) also will be updated to prevent duplicate inserts.\n if (\n (isSubCategory(elementProps) && isDefaultSubCategory(elementProps)) ||\n this._rootElementIds.has(elementProps.id)\n ) {\n await this.onUpdateElement(elementProps);\n } else {\n if (this._elementsToUpdateDuringPreserveIds.has(elementProps.id)) {\n await this.tryUpdateElement(elementProps);\n this._elementsToUpdateDuringPreserveIds.delete(elementProps.id);\n } else {\n await this.onInsertElement(elementProps);\n }\n }\n } else {\n if (undefined !== elementProps.id) {\n await this.tryUpdateElement(elementProps);\n } else {\n elementProps.id = await this.onInsertElement(elementProps); // targetElementProps.id assigned by insertElement\n }\n }\n return elementProps.id;\n }\n\n /** Create a new Element from the specified ElementProps and insert it into the target iModel.\n * @returns The Id of the newly inserted Element.\n * @note A subclass may override this method to customize insert behavior but should call `super.onInsertElement`.\n */\n protected async onInsertElement(\n elementProps: ElementProps\n ): Promise<Id64String> {\n try {\n const elementId = this._editTxn.insertElement(elementProps, {\n forceUseId: this.options.preserveElementIdsForFiltering,\n });\n // set the id like [IModelDb.insertElement]($backend), does, the raw nativeDb method does not\n elementProps.id = elementId;\n Logger.logInfo(\n loggerCategory,\n `Inserted ${this.formatElementForLogger(elementProps)}`\n );\n await this.trackProgress();\n if (this.options.simplifyElementGeometry) {\n this.targetDb.simplifyElementGeometry({\n id: elementId,\n convertBReps: true,\n });\n Logger.logInfo(\n loggerCategory,\n `Simplified element geometry for ${this.formatElementForLogger(\n elementProps\n )}`\n );\n }\n return elementId;\n } catch (error) {\n if (!this.targetDb.containsClass(elementProps.classFullName)) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.TargetClassNotFound,\n },\n message: `Element class \"${elementProps.classFullName}\" not found in the target iModel. Was the latest version of the schema imported?`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n /** Update an existing Element in the target iModel from the specified ElementProps.\n * @note A subclass may override this method to customize update behavior but should call `super.onUpdateElement`.\n */\n protected async onUpdateElement(elementProps: ElementProps): Promise<void> {\n if (!elementProps.id) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.ElementIdRequired,\n },\n message: \"ElementId not provided\",\n });\n }\n this._editTxn.updateElement(elementProps);\n Logger.logInfo(\n loggerCategory,\n `Updated ${this.formatElementForLogger(elementProps)}`\n );\n await this.trackProgress();\n if (this.options.simplifyElementGeometry) {\n this.targetDb.simplifyElementGeometry({\n id: elementProps.id,\n convertBReps: true,\n });\n Logger.logInfo(\n loggerCategory,\n `Simplified element geometry for ${this.formatElementForLogger(\n elementProps\n )}`\n );\n }\n }\n\n /** Deletes one target element tree through [[deleteElements]]. */\n public async deleteElement(elementId: Id64String): Promise<void> {\n await this.deleteElements(new Set([elementId]));\n }\n\n /** Adds roots required by code-scope dependencies, then deletes the target element trees in as few native operations as their references allow.\n * Usually one native operation is enough. When a tree contains a definition, such as a category, that another deleted element uses, the elements that use it are deleted first.\n * Elements that something outside the deleted trees still references are kept, with a warning, and the rest are deleted.\n * @note An override must call `super.onDeleteElements` once to perform the deletion.\n */\n protected async onDeleteElements(\n elementIds: ReadonlySet<Id64String>\n ): Promise<void> {\n const plan = await planBulkDelete(this.targetDb, elementIds);\n if (plan.keptReferences.size > 0) {\n Logger.logWarning(\n loggerCategory,\n `Kept ${plan.keptReferences.size} elements that elements outside the deleted trees still reference, and the elements that contain them: ${formatKeptReferences(\n plan.keptReferences\n )}`\n );\n }\n if (plan.phases.length === 0) return;\n let rootCount = 0;\n for (const roots of plan.phases) {\n rootCount += roots.length;\n this.deleteElementRoots(roots);\n }\n\n Logger.logInfo(\n loggerCategory,\n `Deleted ${elementIds.size} requested element trees using ${rootCount} native deletion roots in ${plan.phases.length} native operations`\n );\n await this.trackProgress(elementIds.size);\n }\n\n private deleteElementRoots(roots: Id64String[]): void {\n const result = this._editTxn.deleteElements(roots);\n if (result.status !== BulkDeleteElementsStatus.Success) {\n ITwinError.throwError<ElementBulkDeleteError>({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.ElementBulkDeleteFailed,\n },\n message:\n `Bulk element deletion failed: status ${BulkDeleteElementsStatus[result.status]}, ` +\n `SQLite status ${result.sqlDeleteStatus}, failed element IDs: ${[\n ...result.failedIds,\n ].join(\", \")}`,\n status: result.status,\n sqlDeleteStatus: result.sqlDeleteStatus,\n failedIds: new Set(result.failedIds),\n });\n }\n }\n\n /** Deletes target element trees, using one native operation unless references between the trees require more.\n * Requested roots in [[doNotUpdateElementIds]] are skipped. This does not prevent an element in that set from being deleted as part of another root's cascade.\n * Elements that something outside the deleted trees still references are kept, along with their child elements and sub-models and the elements that contain them. A warning lists them.\n * @throws [[ElementBulkDeleteError]] if a native operation fails for any root, for example because geometry outside the deleted trees uses a geometry part in them, or because of a reference in a domain schema. The transformer does not check those references first. Deletions from that and earlier native operations stay pending in the caller-owned transaction. Abandon the transaction before retrying.\n */\n public async deleteElements(\n elementIds: ReadonlySet<Id64String>\n ): Promise<void> {\n const idsToDelete = new Set<Id64String>();\n for (const elementId of elementIds) {\n if (!this.doNotUpdateElement(elementId)) {\n idsToDelete.add(elementId);\n continue;\n }\n Logger.logInfo(\n loggerCategory,\n `Do not delete target element ${elementId}`\n );\n }\n if (idsToDelete.size === 0) return;\n await this.onDeleteElements(idsToDelete);\n // Element deletion cascades can remove descendants and their submodels.\n for (const cache of this._entityExistenceCaches)\n cache.clearDb(this.targetDb);\n }\n\n /** Delete the specified Model from the target iModel.\n * @note A subclass may override this method to customize delete behavior but should call `super.onDeleteModel`.\n */\n protected async onDeleteModel(modelId: Id64String): Promise<void> {\n this._editTxn.deleteModel(modelId);\n Logger.logInfo(loggerCategory, `Deleted model ${modelId}`);\n await this.trackProgress();\n }\n\n /** Delete the specified Model from the target iModel. */\n public async deleteModel(modelId: Id64String): Promise<void> {\n await this.onDeleteModel(modelId);\n const modelReference = EntityReferences.fromEntityType(\n modelId,\n ConcreteEntityTypes.Model\n );\n for (const cache of this._entityExistenceCaches)\n cache.invalidate(this.targetDb, modelReference);\n }\n\n /** Format an Element for the Logger. */\n private formatElementForLogger(elementProps: ElementProps): string {\n const namePiece: string = elementProps.code.value\n ? `${elementProps.code.value} `\n : elementProps.userLabel\n ? `${elementProps.userLabel} `\n : \"\";\n return `${elementProps.classFullName} ${namePiece}[${elementProps.id}]`;\n }\n\n /** Import an ElementUniqueAspect into the target iModel. */\n public async importElementUniqueAspect(\n aspectProps: ElementAspectProps\n ): Promise<Id64String> {\n const aspects: ElementAspect[] = this.targetDb.elements.getAspects(\n aspectProps.element.id,\n aspectProps.classFullName\n );\n if (aspects.length === 0) {\n return this.onInsertElementAspect(aspectProps);\n } else if (hasEntityChanged(aspects[0], aspectProps)) {\n aspectProps.id = aspects[0].id;\n await this.onUpdateElementAspect(aspectProps);\n }\n return aspects[0].id;\n }\n\n /** Import the collection of ElementMultiAspects into the target iModel.\n * @param aspectPropsArray The ElementMultiAspects to import\n * @param filterFunc Optional filter func that is used to exclude target ElementMultiAspects that were added during iModel transformation from the update detection logic.\n * @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.\n * @returns the array of ids of the resulting ElementMultiAspects, in the same order of the aspectPropsArray parameter\n */\n public async importElementMultiAspects(\n aspectPropsArray: ElementAspectProps[],\n /** caller must use this to enforce any aspects added by IModelTransformer are not considered for update */\n filterFunc: (a: ElementMultiAspect) => boolean = () => true\n ): Promise<Id64String[]> {\n const result = new Array<Id64String | undefined>(\n aspectPropsArray.length\n ).fill(undefined);\n\n if (aspectPropsArray.length === 0) {\n return result as Id64String[];\n }\n\n const elementId: Id64String = aspectPropsArray[0].element.id;\n const proposedAspectsByClass = new Map<\n string,\n Array<{ props: ElementAspectProps; index: number }>\n >();\n aspectPropsArray.forEach((props, index): void => {\n const proposedAspects =\n proposedAspectsByClass.get(props.classFullName) ?? [];\n proposedAspects.push({ props, index });\n proposedAspectsByClass.set(props.classFullName, proposedAspects);\n });\n\n // Handle ElementMultiAspects in groups by class\n for (const [\n aspectClassFullName,\n proposedAspects,\n ] of proposedAspectsByClass) {\n const currentAspects = this.targetDb.elements\n .getAspects(elementId, aspectClassFullName)\n .map((props, index) => ({ props, index }) as const)\n .filter(({ props }) => filterFunc(props));\n\n if (proposedAspects.length >= currentAspects.length) {\n for (let index = 0; index < proposedAspects.length; index++) {\n const { props, index: resultIndex } = proposedAspects[index];\n let id: Id64String;\n if (index < currentAspects.length) {\n id = currentAspects[index].props.id;\n props.id = id;\n if (hasEntityChanged(currentAspects[index].props, props)) {\n await this.onUpdateElementAspect(props);\n }\n id = props.id;\n } else {\n id = await this.onInsertElementAspect(props);\n }\n result[resultIndex] = id;\n }\n } else {\n for (let index = 0; index < currentAspects.length; index++) {\n const { props } = currentAspects[index];\n if (index < proposedAspects.length) {\n const { props: proposedProps, index: resultIndex } =\n proposedAspects[index];\n const id = props.id;\n proposedProps.id = id;\n if (hasEntityChanged(props, proposedProps)) {\n await this.onUpdateElementAspect(proposedProps);\n }\n result[resultIndex] = id;\n } else {\n await this.onDeleteElementAspect(props);\n }\n }\n }\n }\n\n assert(result.every((r) => r !== undefined));\n return result;\n }\n\n /** Insert the ElementAspect into the target iModel.\n * @note A subclass may override this method to customize insert behavior but should call `super.onInsertElementAspect`.\n */\n protected async onInsertElementAspect(\n aspectProps: ElementAspectProps\n ): Promise<Id64String> {\n try {\n const id = this._editTxn.insertAspect(aspectProps);\n Logger.logInfo(\n loggerCategory,\n `Inserted ${this.formatElementAspectForLogger(aspectProps)}`\n );\n await this.trackProgress();\n return id;\n } catch (error) {\n if (!this.targetDb.containsClass(aspectProps.classFullName)) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.TargetClassNotFound,\n },\n message: `ElementAspect class \"${aspectProps.classFullName}\" not found in the target iModel. Was the latest version of the schema imported?`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n /** Update the ElementAspect within the target iModel.\n * @note A subclass may override this method to customize update behavior but should call `super.onUpdateElementAspect`.\n */\n protected async onUpdateElementAspect(\n aspectProps: ElementAspectProps\n ): Promise<void> {\n this._editTxn.updateAspect(aspectProps);\n Logger.logInfo(\n loggerCategory,\n `Updated ${this.formatElementAspectForLogger(aspectProps)}`\n );\n await this.trackProgress();\n }\n\n /** Delete the specified ElementAspect from the target iModel.\n * @note A subclass may override this method to customize delete behavior but should call `super.onDeleteElementAspect`.\n */\n protected async onDeleteElementAspect(\n targetElementAspect: ElementAspect\n ): Promise<void> {\n this._editTxn.deleteAspect(targetElementAspect.id);\n Logger.logInfo(\n loggerCategory,\n `Deleted ${this.formatElementAspectForLogger(targetElementAspect)}`\n );\n await this.trackProgress();\n }\n\n /** Format an ElementAspect for the Logger. */\n private formatElementAspectForLogger(\n elementAspectProps: ElementAspectProps | ElementAspect\n ): string {\n return `${elementAspectProps.classFullName} elementId=[${elementAspectProps.element.id}]`;\n }\n\n /** Import the specified RelationshipProps (either as an insert or an update) into the target iModel.\n * @returns The instance Id of the inserted or updated Relationship.\n */\n public async importRelationship(\n relationshipProps: RelationshipProps\n ): Promise<Id64String> {\n if (\n undefined === relationshipProps.sourceId ||\n !Id64.isValidId64(relationshipProps.sourceId)\n ) {\n Logger.logInfo(\n loggerCategory,\n `Ignoring ${relationshipProps.classFullName} instance because of invalid RelationshipProps.sourceId`\n );\n return Id64.invalid;\n }\n if (\n undefined === relationshipProps.targetId ||\n !Id64.isValidId64(relationshipProps.targetId)\n ) {\n Logger.logInfo(\n loggerCategory,\n `Ignoring ${relationshipProps.classFullName} instance because of invalid RelationshipProps.targetId`\n );\n return Id64.invalid;\n }\n // check for an existing relationship\n const relSourceAndTarget: SourceAndTarget = {\n sourceId: relationshipProps.sourceId,\n targetId: relationshipProps.targetId,\n };\n const relationship: Relationship | undefined =\n this.targetDb.relationships.tryGetInstance(\n relationshipProps.classFullName,\n relSourceAndTarget\n );\n if (undefined !== relationship) {\n // if relationship found, update it\n relationshipProps.id = relationship.id;\n if (hasEntityChanged(relationship, relationshipProps)) {\n await this.onUpdateRelationship(relationshipProps);\n }\n return relationshipProps.id;\n } else {\n return this.onInsertRelationship(relationshipProps);\n }\n }\n\n /** Create a new Relationship from the specified RelationshipProps and insert it into the target iModel.\n * @returns The instance Id of the newly inserted relationship.\n * @note A subclass may override this method to customize insert behavior but should call `super.onInsertRelationship`.\n */\n protected async onInsertRelationship(\n relationshipProps: RelationshipProps\n ): Promise<Id64String> {\n try {\n const targetRelInstanceId: Id64String =\n this._editTxn.insertRelationship(relationshipProps);\n Logger.logInfo(\n loggerCategory,\n `Inserted ${this.formatRelationshipForLogger(relationshipProps)}`\n );\n await this.trackProgress();\n return targetRelInstanceId;\n } catch (error) {\n if (!this.targetDb.containsClass(relationshipProps.classFullName)) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.TargetClassNotFound,\n },\n message: `Relationship class \"${relationshipProps.classFullName}\" not found in the target iModel. Was the latest version of the schema imported?`,\n cause: error,\n });\n }\n throw error;\n }\n }\n\n /** Update an existing Relationship in the target iModel from the specified RelationshipProps.\n * @note A subclass may override this method to customize update behavior but should call `super.onUpdateRelationship`.\n */\n protected async onUpdateRelationship(\n relationshipProps: RelationshipProps\n ): Promise<void> {\n if (!relationshipProps.id) {\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.RelationshipIdRequired,\n },\n message: \"Relationship instance Id not provided\",\n });\n }\n this._editTxn.updateRelationship(relationshipProps);\n Logger.logInfo(\n loggerCategory,\n `Updated ${this.formatRelationshipForLogger(relationshipProps)}`\n );\n await this.trackProgress();\n }\n\n /** Delete the specified Relationship from the target iModel. */\n protected async onDeleteRelationship(\n relationshipProps: RelationshipPropsForDelete\n ): Promise<void> {\n // Only passing in what deleteInstance actually uses, full relationshipProps is not necessary.\n this._editTxn.deleteRelationship({\n id: relationshipProps.id,\n classFullName: relationshipProps.classFullName,\n } as RelationshipProps);\n Logger.logInfo(\n loggerCategory,\n `Deleted relationship ${relationshipProps.classFullName} id=${relationshipProps.id}`\n );\n await this.trackProgress();\n }\n\n /** Delete the specified Relationship from the target iModel. */\n public async deleteRelationship(\n relationshipProps: RelationshipPropsForDelete\n ): Promise<void> {\n await this.onDeleteRelationship(relationshipProps);\n }\n\n /** Format a Relationship for the Logger. */\n private formatRelationshipForLogger(relProps: RelationshipProps): string {\n return `${relProps.classFullName} sourceId=[${relProps.sourceId}] targetId=[${relProps.targetId}]`;\n }\n\n /** Tracks incremental progress */\n private async trackProgress(increment = 1): Promise<void> {\n const previousProgressCounter = this._progressCounter;\n this._progressCounter += increment;\n const progressCallbacks =\n Math.floor(this._progressCounter / this.progressInterval) -\n Math.floor(previousProgressCounter / this.progressInterval);\n for (let i = 0; i < progressCallbacks; ++i) await this.onProgress();\n }\n\n /** This method is called when IModelImporter has made incremental progress based on the [[progressInterval]] setting.\n * @note A subclass may override this method to report custom progress but should call `super.onProgress`.\n */\n protected async onProgress(): Promise<void> {}\n\n /** Optionally compute the projectExtents for the target iModel depending on the options for this IModelImporter.\n * @note This method is automatically called from [IModelTransformer.process]($transformer).\n * @see [IModelDb.computeProjectExtents]($backend), [[autoExtendProjectExtents]]\n */\n public computeProjectExtents(): void {\n const computedProjectExtents = this.targetDb.computeProjectExtents({\n reportExtentsWithOutliers: true,\n reportOutliers: true,\n });\n Logger.logInfo(\n loggerCategory,\n `Current projectExtents=${JSON.stringify(this.targetDb.projectExtents)}`\n );\n Logger.logInfo(\n loggerCategory,\n `Computed projectExtents without outliers=${JSON.stringify(\n computedProjectExtents.extents\n )}`\n );\n Logger.logInfo(\n loggerCategory,\n `Computed projectExtents with outliers=${JSON.stringify(\n computedProjectExtents.extentsWithOutliers\n )}`\n );\n if (this.options.autoExtendProjectExtents) {\n const excludeOutliers: boolean =\n typeof this.options.autoExtendProjectExtents === \"object\"\n ? this.options.autoExtendProjectExtents.excludeOutliers\n : false;\n // If excludeOutliers is true, use the extents without outliers.\n // Otherwise prefer extentsWithOutliers, but fall back to extents if it's undefined or a null range.\n const extentsWithOutliers = computedProjectExtents.extentsWithOutliers;\n const useExtentsWithOutliers =\n !excludeOutliers && extentsWithOutliers && !extentsWithOutliers.isNull;\n const newProjectExtents = useExtentsWithOutliers\n ? extentsWithOutliers\n : computedProjectExtents.extents;\n if (!newProjectExtents.isAlmostEqual(this.targetDb.projectExtents)) {\n this._editTxn.updateProjectExtents(newProjectExtents);\n Logger.logInfo(\n loggerCategory,\n `Updated projectExtents=${JSON.stringify(\n this.targetDb.projectExtents\n )}`\n );\n }\n if (\n !excludeOutliers &&\n computedProjectExtents.outliers &&\n computedProjectExtents.outliers.length > 0\n ) {\n Logger.logInfo(\n loggerCategory,\n `${computedProjectExtents.outliers.length} outliers detected within projectExtents`\n );\n }\n } else {\n if (\n !this.targetDb.projectExtents.containsRange(\n computedProjectExtents.extents\n )\n ) {\n Logger.logWarning(\n loggerCategory,\n \"Current project extents may be too small\"\n );\n }\n if (\n computedProjectExtents.outliers &&\n computedProjectExtents.outliers.length > 0\n ) {\n Logger.logInfo(\n loggerCategory,\n `${computedProjectExtents.outliers.length} outliers detected within projectExtents`\n );\n }\n }\n }\n\n /** Examine the geometry streams of every [GeometricElement3d]($backend) in the target iModel and apply the specified optimizations.\n * @note This method is automatically called from [[IModelTransformer.process]] if\n * [[IModelTransformOptions.optimizeGeometry]] is defined.\n */\n public optimizeGeometry(options: OptimizeGeometryOptions): void {\n if (options.inlineUniqueGeometryParts) {\n const result = this.targetDb.inlineGeometryParts();\n Logger.logInfo(\n loggerCategory,\n `Inlined ${result.numRefsInlined} references to ${result.numCandidateParts} geometry parts and deleted ${result.numPartsDeleted} parts.`\n );\n }\n }\n\n private resolveDuplicateCodeValues(): void {\n for (const [elementId, codeValue] of this._duplicateCodeValueMap) {\n const element = this.targetDb.elements.getElement(elementId);\n element.code.value = codeValue;\n this._editTxn.updateElement(element.toJSON());\n }\n this._duplicateCodeValueMap.clear();\n }\n\n /**\n * Needs to be called to perform necessary cleanup operations.\n * By not calling `finalize` there is a risk that data imported into targetDb will not be as expected.\n *\n * @note [[IModelTransformer.process]] invokes this method automatically. Call it explicitly after\n * composing the transformer's lower-level subset processing methods.\n */\n public finalize(): void {\n this.resolveDuplicateCodeValues();\n }\n}\n\n/** Returns true if a change within an Entity is detected.\n * @param entity The current persistent Entity.\n * @param entityProps The new EntityProps to compare against\n * @note This method should only be called if changeset information is not available.\n * @internal\n */\nexport function hasEntityChanged(\n entity: Entity,\n entityProps: EntityProps,\n namesToIgnore?: Set<string>\n): boolean {\n let changed: boolean = false;\n const entityClass = entity.iModel.schemaContext.getSchemaItemSync(\n entity.schemaItemKey\n );\n assert(\n EntityClass.isEntityClass(entityClass) ||\n RelationshipClass.isRelationshipClass(entityClass),\n `Cannot get metadata for ${entity.classFullName}.`\n );\n for (const property of entityClass.getPropertiesSync()) {\n const propertyName = property.name;\n if (!changed) {\n if (namesToIgnore && namesToIgnore.has(propertyName)) {\n // skip\n } else if (PropertyType.Binary === property.propertyType) {\n changed = hasBinaryValueChanged(\n entity.asAny[ECJsNames.toJsName(propertyName)],\n (entityProps as any)[ECJsNames.toJsName(propertyName)]\n );\n } else if (property.isNavigation()) {\n changed = hasNavigationValueChanged(\n entity.asAny[ECJsNames.toJsName(propertyName)],\n (entityProps as any)[ECJsNames.toJsName(propertyName)]\n );\n } else {\n changed = hasValueChanged(\n entity.asAny[ECJsNames.toJsName(propertyName)],\n (entityProps as any)[ECJsNames.toJsName(propertyName)]\n );\n }\n }\n }\n return changed;\n}\n\n/** Returns true if the specified binary values are different. */\nfunction hasBinaryValueChanged(\n binaryProperty1: any,\n binaryProperty2: any\n): boolean {\n const jsonString1 = JSON.stringify(\n binaryProperty1,\n Base64EncodedString.replacer\n );\n const jsonString2 = JSON.stringify(\n binaryProperty2,\n Base64EncodedString.replacer\n );\n return jsonString1 !== jsonString2;\n}\n\n/** Returns true if the specified navigation property values are different. */\nfunction hasNavigationValueChanged(\n navigationProperty1: any,\n navigationProperty2: any\n): boolean {\n const relatedElement1 = RelatedElement.fromJSON(navigationProperty1);\n const relatedElement2 = RelatedElement.fromJSON(navigationProperty2);\n const jsonString1 = JSON.stringify(relatedElement1);\n const jsonString2 = JSON.stringify(relatedElement2);\n return jsonString1 !== jsonString2;\n}\n\n/** Returns true if the specified navigation property values are different. */\nfunction hasValueChanged(property1: any, property2: any): boolean {\n return JSON.stringify(property1) !== JSON.stringify(property2);\n}\n\n/** check if element props are a subcategory */\nfunction isSubCategory(props: ElementProps): props is SubCategoryProps {\n return props.classFullName === SubCategory.classFullName;\n}\n\n/** check if element props are a subcategory without loading the element */\nfunction isDefaultSubCategory(props: SubCategoryProps): boolean {\n if (props.id === undefined) return false;\n\n if (!Id64.isId64(props.id))\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.InvalidSubCategory,\n },\n message: \"subcategory had invalid id\",\n });\n if (props.parent?.id === undefined)\n ITwinError.throwError({\n iTwinErrorId: {\n scope: IModelTransformerErrorScope,\n key: IModelTransformerError.InvalidSubCategory,\n },\n message: `subcategory with id ${props.id} had no parent`,\n });\n return props.id === IModelDb.getDefaultSubCategoryId(props.parent.id);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/imodel-transformer",
3
- "version": "2.0.0-dev.60",
3
+ "version": "2.0.0-dev.61",
4
4
  "description": "API for exporting an iModel's parts and also importing them into another iModel",
5
5
  "main": "lib/cjs/imodel-transformer.js",
6
6
  "typings": "lib/cjs/imodel-transformer.d.ts",