@itwin/core-backend 4.0.0-dev.21 → 4.0.0-dev.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/AliCloudStorageService.d.ts +23 -23
- package/lib/cjs/AliCloudStorageService.js +71 -71
- package/lib/cjs/AliCloudStorageService.js.map +1 -1
- package/lib/cjs/BackendHubAccess.d.ts +224 -224
- package/lib/cjs/BackendHubAccess.js +41 -41
- package/lib/cjs/BackendHubAccess.js.map +1 -1
- package/lib/cjs/BackendLoggerCategory.d.ts +91 -91
- package/lib/cjs/BackendLoggerCategory.js +99 -99
- package/lib/cjs/BackendLoggerCategory.js.map +1 -1
- package/lib/cjs/BisCoreSchema.d.ts +21 -21
- package/lib/cjs/BisCoreSchema.js +60 -60
- package/lib/cjs/BisCoreSchema.js.map +1 -1
- package/lib/cjs/BriefcaseManager.d.ts +170 -170
- package/lib/cjs/BriefcaseManager.js +414 -414
- package/lib/cjs/BriefcaseManager.js.map +1 -1
- package/lib/cjs/Category.d.ts +153 -153
- package/lib/cjs/Category.js +243 -243
- package/lib/cjs/Category.js.map +1 -1
- package/lib/cjs/ChangeSummaryManager.d.ts +187 -187
- package/lib/cjs/ChangeSummaryManager.js +447 -447
- package/lib/cjs/ChangeSummaryManager.js.map +1 -1
- package/lib/cjs/ChangedElementsDb.d.ts +99 -99
- package/lib/cjs/ChangedElementsDb.js +165 -165
- package/lib/cjs/ChangedElementsDb.js.map +1 -1
- package/lib/cjs/ChangedElementsManager.d.ts +39 -39
- package/lib/cjs/ChangedElementsManager.js +88 -88
- package/lib/cjs/ChangedElementsManager.js.map +1 -1
- package/lib/cjs/CheckpointManager.d.ts +121 -121
- package/lib/cjs/CheckpointManager.js +349 -349
- package/lib/cjs/CheckpointManager.js.map +1 -1
- package/lib/cjs/ClassRegistry.d.ts +79 -79
- package/lib/cjs/ClassRegistry.js +250 -250
- package/lib/cjs/ClassRegistry.js.map +1 -1
- package/lib/cjs/CloudSqlite.d.ts +350 -350
- package/lib/cjs/CloudSqlite.js +153 -153
- package/lib/cjs/CloudSqlite.js.map +1 -1
- package/lib/cjs/CloudStorageBackend.d.ts +58 -58
- package/lib/cjs/CloudStorageBackend.js +173 -173
- package/lib/cjs/CloudStorageBackend.js.map +1 -1
- package/lib/cjs/CodeService.d.ts +396 -396
- package/lib/cjs/CodeService.js +63 -63
- package/lib/cjs/CodeService.js.map +1 -1
- package/lib/cjs/CodeSpecs.d.ts +55 -55
- package/lib/cjs/CodeSpecs.js +124 -124
- package/lib/cjs/CodeSpecs.js.map +1 -1
- package/lib/cjs/ConcurrentQuery.d.ts +13 -13
- package/lib/cjs/ConcurrentQuery.js +36 -36
- package/lib/cjs/ConcurrentQuery.js.map +1 -1
- package/lib/cjs/CustomViewState3dCreator.d.ts +21 -21
- package/lib/cjs/CustomViewState3dCreator.js +81 -81
- package/lib/cjs/CustomViewState3dCreator.js.map +1 -1
- package/lib/cjs/DevTools.d.ts +73 -73
- package/lib/cjs/DevTools.js +156 -156
- package/lib/cjs/DevTools.js.map +1 -1
- package/lib/cjs/DisplayStyle.d.ts +106 -106
- package/lib/cjs/DisplayStyle.js +256 -256
- package/lib/cjs/DisplayStyle.js.map +1 -1
- package/lib/cjs/ECDb.d.ts +191 -191
- package/lib/cjs/ECDb.js +350 -350
- package/lib/cjs/ECDb.js.map +1 -1
- package/lib/cjs/ECSchemaXmlContext.d.ts +18 -18
- package/lib/cjs/ECSchemaXmlContext.js +41 -41
- package/lib/cjs/ECSchemaXmlContext.js.map +1 -1
- package/lib/cjs/ECSqlStatement.d.ts +473 -473
- package/lib/cjs/ECSqlStatement.js +791 -791
- package/lib/cjs/ECSqlStatement.js.map +1 -1
- package/lib/cjs/Element.d.ts +1109 -1109
- package/lib/cjs/Element.js +1427 -1427
- package/lib/cjs/Element.js.map +1 -1
- package/lib/cjs/ElementAspect.d.ts +179 -179
- package/lib/cjs/ElementAspect.js +211 -211
- package/lib/cjs/ElementAspect.js.map +1 -1
- package/lib/cjs/ElementGraphics.d.ts +9 -9
- package/lib/cjs/ElementGraphics.js +41 -41
- package/lib/cjs/ElementGraphics.js.map +1 -1
- package/lib/cjs/ElementTreeWalker.d.ts +162 -162
- package/lib/cjs/ElementTreeWalker.js +409 -409
- package/lib/cjs/ElementTreeWalker.js.map +1 -1
- package/lib/cjs/Entity.d.ts +106 -106
- package/lib/cjs/Entity.js +134 -134
- package/lib/cjs/Entity.js.map +1 -1
- package/lib/cjs/EntityReferences.d.ts +49 -49
- package/lib/cjs/EntityReferences.js +95 -95
- package/lib/cjs/EntityReferences.js.map +1 -1
- package/lib/cjs/ExportGraphics.d.ts +317 -317
- package/lib/cjs/ExportGraphics.js +208 -208
- package/lib/cjs/ExportGraphics.js.map +1 -1
- package/lib/cjs/ExternalSource.d.ts +96 -96
- package/lib/cjs/ExternalSource.js +131 -131
- package/lib/cjs/ExternalSource.js.map +1 -1
- package/lib/cjs/GeoCoordConfig.d.ts +19 -19
- package/lib/cjs/GeoCoordConfig.js +85 -85
- package/lib/cjs/GeoCoordConfig.js.map +1 -1
- package/lib/cjs/GeometrySummary.d.ts +4 -4
- package/lib/cjs/GeometrySummary.js +380 -380
- package/lib/cjs/GeometrySummary.js.map +1 -1
- package/lib/cjs/HubMock.d.ts +94 -94
- package/lib/cjs/HubMock.js +222 -222
- package/lib/cjs/HubMock.js.map +1 -1
- package/lib/cjs/IModelCloneContext.d.ts +8 -8
- package/lib/cjs/IModelCloneContext.js +15 -15
- package/lib/cjs/IModelCloneContext.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +1196 -1196
- package/lib/cjs/IModelDb.js +2392 -2392
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/IModelElementCloneContext.d.ts +89 -89
- package/lib/cjs/IModelElementCloneContext.js +159 -159
- package/lib/cjs/IModelElementCloneContext.js.map +1 -1
- package/lib/cjs/IModelHost.d.ts +369 -369
- package/lib/cjs/IModelHost.js +496 -496
- package/lib/cjs/IModelHost.js.map +1 -1
- package/lib/cjs/IModelJsFs.d.ts +62 -62
- package/lib/cjs/IModelJsFs.js +140 -140
- package/lib/cjs/IModelJsFs.js.map +1 -1
- package/lib/cjs/IpcHost.d.ts +104 -104
- package/lib/cjs/IpcHost.js +278 -278
- package/lib/cjs/IpcHost.js.map +1 -1
- package/lib/cjs/LineStyle.d.ts +311 -311
- package/lib/cjs/LineStyle.js +295 -295
- package/lib/cjs/LineStyle.js.map +1 -1
- package/lib/cjs/LocalHub.d.ts +162 -162
- package/lib/cjs/LocalHub.js +585 -585
- package/lib/cjs/LocalHub.js.map +1 -1
- package/lib/cjs/LocalhostIpcHost.d.ts +20 -20
- package/lib/cjs/LocalhostIpcHost.js +81 -81
- package/lib/cjs/LocalhostIpcHost.js.map +1 -1
- package/lib/cjs/Material.d.ts +131 -131
- package/lib/cjs/Material.js +181 -181
- package/lib/cjs/Material.js.map +1 -1
- package/lib/cjs/Model.d.ts +392 -392
- package/lib/cjs/Model.js +485 -485
- package/lib/cjs/Model.js.map +1 -1
- package/lib/cjs/NativeAppStorage.d.ts +51 -51
- package/lib/cjs/NativeAppStorage.js +202 -202
- package/lib/cjs/NativeAppStorage.js.map +1 -1
- package/lib/cjs/NativeHost.d.ts +52 -52
- package/lib/cjs/NativeHost.js +163 -163
- package/lib/cjs/NativeHost.js.map +1 -1
- package/lib/cjs/NavigationRelationship.d.ts +156 -156
- package/lib/cjs/NavigationRelationship.js +225 -225
- package/lib/cjs/NavigationRelationship.js.map +1 -1
- package/lib/cjs/PromiseMemoizer.d.ts +51 -51
- package/lib/cjs/PromiseMemoizer.js +101 -101
- package/lib/cjs/PromiseMemoizer.js.map +1 -1
- package/lib/cjs/PropertyStore.d.ts +132 -132
- package/lib/cjs/PropertyStore.js +11 -11
- package/lib/cjs/PropertyStore.js.map +1 -1
- package/lib/cjs/Relationship.d.ts +416 -416
- package/lib/cjs/Relationship.js +494 -494
- package/lib/cjs/Relationship.js.map +1 -1
- package/lib/cjs/RpcBackend.d.ts +5 -5
- package/lib/cjs/RpcBackend.js +32 -32
- package/lib/cjs/RpcBackend.js.map +1 -1
- package/lib/cjs/SQLiteDb.d.ts +219 -219
- package/lib/cjs/SQLiteDb.js +214 -214
- package/lib/cjs/SQLiteDb.js.map +1 -1
- package/lib/cjs/Schema.d.ts +55 -55
- package/lib/cjs/Schema.js +83 -83
- package/lib/cjs/Schema.js.map +1 -1
- package/lib/cjs/ServerBasedLocks.d.ts +57 -57
- package/lib/cjs/ServerBasedLocks.js +168 -168
- package/lib/cjs/ServerBasedLocks.js.map +1 -1
- package/lib/cjs/SqliteStatement.d.ts +360 -360
- package/lib/cjs/SqliteStatement.js +586 -586
- package/lib/cjs/SqliteStatement.js.map +1 -1
- package/lib/cjs/Texture.d.ts +58 -58
- package/lib/cjs/Texture.js +82 -82
- package/lib/cjs/Texture.js.map +1 -1
- package/lib/cjs/TileStorage.d.ts +18 -18
- package/lib/cjs/TileStorage.js +90 -90
- package/lib/cjs/TileStorage.js.map +1 -1
- package/lib/cjs/TxnManager.d.ts +202 -202
- package/lib/cjs/TxnManager.js +356 -356
- package/lib/cjs/TxnManager.js.map +1 -1
- package/lib/cjs/ViewDefinition.d.ts +439 -439
- package/lib/cjs/ViewDefinition.js +646 -646
- package/lib/cjs/ViewDefinition.js.map +1 -1
- package/lib/cjs/ViewStateHydrator.d.ts +13 -13
- package/lib/cjs/ViewStateHydrator.js +103 -103
- package/lib/cjs/ViewStateHydrator.js.map +1 -1
- package/lib/cjs/assets/IModelChange.02.00.00.ecschema.xml +90 -90
- package/lib/cjs/assets/Settings/Schemas/Cloud.Schema.json +67 -67
- package/lib/cjs/assets/Settings/Schemas/Gcs.schema.json +31 -31
- package/lib/cjs/assets/Settings/Schemas/Workspace.Schema.json +52 -52
- package/lib/cjs/assets/Settings/backend.setting.json5 +138 -138
- package/lib/cjs/core-backend.d.ts +184 -184
- package/lib/cjs/core-backend.js +204 -204
- package/lib/cjs/core-backend.js.map +1 -1
- package/lib/cjs/domains/FunctionalElements.d.ts +101 -101
- package/lib/cjs/domains/FunctionalElements.js +145 -145
- package/lib/cjs/domains/FunctionalElements.js.map +1 -1
- package/lib/cjs/domains/FunctionalSchema.d.ts +13 -13
- package/lib/cjs/domains/FunctionalSchema.js +40 -40
- package/lib/cjs/domains/FunctionalSchema.js.map +1 -1
- package/lib/cjs/domains/GenericElements.d.ts +177 -177
- package/lib/cjs/domains/GenericElements.js +263 -263
- package/lib/cjs/domains/GenericElements.js.map +1 -1
- package/lib/cjs/domains/GenericSchema.d.ts +10 -10
- package/lib/cjs/domains/GenericSchema.js +28 -28
- package/lib/cjs/domains/GenericSchema.js.map +1 -1
- package/lib/cjs/rpc/multipart.d.ts +11 -11
- package/lib/cjs/rpc/multipart.js +71 -71
- package/lib/cjs/rpc/multipart.js.map +1 -1
- package/lib/cjs/rpc/tracing.d.ts +28 -28
- package/lib/cjs/rpc/tracing.js +74 -74
- package/lib/cjs/rpc/tracing.js.map +1 -1
- package/lib/cjs/rpc/web/logging.d.ts +9 -9
- package/lib/cjs/rpc/web/logging.js +43 -43
- package/lib/cjs/rpc/web/logging.js.map +1 -1
- package/lib/cjs/rpc/web/request.d.ts +6 -6
- package/lib/cjs/rpc/web/request.js +74 -74
- package/lib/cjs/rpc/web/request.js.map +1 -1
- package/lib/cjs/rpc/web/response.d.ts +6 -6
- package/lib/cjs/rpc/web/response.js +106 -106
- package/lib/cjs/rpc/web/response.js.map +1 -1
- package/lib/cjs/rpc-impl/DevToolsRpcImpl.d.ts +15 -15
- package/lib/cjs/rpc-impl/DevToolsRpcImpl.js +32 -32
- package/lib/cjs/rpc-impl/DevToolsRpcImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.d.ts +47 -47
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.js +294 -294
- package/lib/cjs/rpc-impl/IModelReadRpcImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/IModelTileRpcImpl.d.ts +22 -22
- package/lib/cjs/rpc-impl/IModelTileRpcImpl.js +205 -205
- package/lib/cjs/rpc-impl/IModelTileRpcImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/RpcBriefcaseUtility.d.ts +36 -36
- package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js +168 -168
- package/lib/cjs/rpc-impl/RpcBriefcaseUtility.js.map +1 -1
- package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.d.ts +16 -16
- package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.js +43 -43
- package/lib/cjs/rpc-impl/SnapshotIModelRpcImpl.js.map +1 -1
- package/lib/cjs/rpc-impl/WipRpcImpl.d.ts +15 -15
- package/lib/cjs/rpc-impl/WipRpcImpl.js +37 -37
- package/lib/cjs/rpc-impl/WipRpcImpl.js.map +1 -1
- package/lib/cjs/workspace/Settings.d.ts +186 -186
- package/lib/cjs/workspace/Settings.js +155 -155
- package/lib/cjs/workspace/Settings.js.map +1 -1
- package/lib/cjs/workspace/SettingsSchemas.d.ts +75 -75
- package/lib/cjs/workspace/SettingsSchemas.js +191 -191
- package/lib/cjs/workspace/SettingsSchemas.js.map +1 -1
- package/lib/cjs/workspace/Workspace.d.ts +414 -414
- package/lib/cjs/workspace/Workspace.js +543 -543
- package/lib/cjs/workspace/Workspace.js.map +1 -1
- package/package.json +11 -11
|
@@ -1,410 +1,410 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.deleteElementSubTrees = exports.deleteElementTree = exports.ElementSubTreeDeleter = exports.ElementTreeDeleter = exports.ElementTreeBottomUp = exports.ElementTreeWalkerScope = void 0;
|
|
4
|
-
/*---------------------------------------------------------------------------------------------
|
|
5
|
-
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
6
|
-
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
7
|
-
*--------------------------------------------------------------------------------------------*/
|
|
8
|
-
/** @packageDocumentation
|
|
9
|
-
* @module Elements
|
|
10
|
-
*/
|
|
11
|
-
const core_bentley_1 = require("@itwin/core-bentley");
|
|
12
|
-
const core_common_1 = require("@itwin/core-common");
|
|
13
|
-
const BackendLoggerCategory_1 = require("./BackendLoggerCategory");
|
|
14
|
-
const Element_1 = require("./Element");
|
|
15
|
-
const IModelDb_1 = require("./IModelDb");
|
|
16
|
-
const Model_1 = require("./Model");
|
|
17
|
-
const loggerCategory = `${BackendLoggerCategory_1.BackendLoggerCategory.IModelDb}.ElementTreeWalker`;
|
|
18
|
-
function sortChildrenBeforeParents(iModel, ids) {
|
|
19
|
-
const children = [];
|
|
20
|
-
const parents = [];
|
|
21
|
-
for (const eid of ids) {
|
|
22
|
-
const parentId = iModel.elements.queryParent(eid);
|
|
23
|
-
if (parentId !== undefined && ids.includes(parentId))
|
|
24
|
-
children.push(eid);
|
|
25
|
-
else
|
|
26
|
-
parents.push(eid);
|
|
27
|
-
}
|
|
28
|
-
if (children.length === 0)
|
|
29
|
-
return [parents];
|
|
30
|
-
return [...sortChildrenBeforeParents(iModel, children), parents];
|
|
31
|
-
}
|
|
32
|
-
function isModelEmpty(iModel, modelId) {
|
|
33
|
-
return iModel.withPreparedStatement(`select count(*) from ${Element_1.Element.classFullName} where Model.Id = ?`, (stmt) => {
|
|
34
|
-
stmt.bindId(1, modelId);
|
|
35
|
-
stmt.step();
|
|
36
|
-
return stmt.getValue(0).getInteger() === 0;
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
function isDefinitionModel(model) {
|
|
40
|
-
return (model.id !== core_common_1.IModel.repositoryModelId) && (model instanceof Model_1.DefinitionModel);
|
|
41
|
-
}
|
|
42
|
-
var ElementPruningClassification;
|
|
43
|
-
(function (ElementPruningClassification) {
|
|
44
|
-
ElementPruningClassification[ElementPruningClassification["PRUNING_CLASS_Normal"] = 0] = "PRUNING_CLASS_Normal";
|
|
45
|
-
ElementPruningClassification[ElementPruningClassification["PRUNING_CLASS_Subject"] = 1] = "PRUNING_CLASS_Subject";
|
|
46
|
-
ElementPruningClassification[ElementPruningClassification["PRUNING_CLASS_Definition"] = 2] = "PRUNING_CLASS_Definition";
|
|
47
|
-
ElementPruningClassification[ElementPruningClassification["PRUNING_CLASS_DefinitionPartition"] = 3] = "PRUNING_CLASS_DefinitionPartition";
|
|
48
|
-
})(ElementPruningClassification || (ElementPruningClassification = {}));
|
|
49
|
-
function classifyElementForPruning(iModel, elementId) {
|
|
50
|
-
const el = iModel.elements.getElement(elementId);
|
|
51
|
-
return (el instanceof Element_1.Subject) ? ElementPruningClassification.PRUNING_CLASS_Subject :
|
|
52
|
-
(el instanceof Element_1.DefinitionElement) ? ElementPruningClassification.PRUNING_CLASS_Definition :
|
|
53
|
-
(el instanceof Element_1.DefinitionPartition) ? ElementPruningClassification.PRUNING_CLASS_DefinitionPartition :
|
|
54
|
-
ElementPruningClassification.PRUNING_CLASS_Normal;
|
|
55
|
-
}
|
|
56
|
-
/** Records the path that a tree search took to reach an element or model. This object is immutable.
|
|
57
|
-
* @beta
|
|
58
|
-
*/
|
|
59
|
-
class ElementTreeWalkerScope {
|
|
60
|
-
constructor(arg1, arg2) {
|
|
61
|
-
this.topElement = "";
|
|
62
|
-
/** path of parent elements and enclosing models */
|
|
63
|
-
this.path = [];
|
|
64
|
-
if (typeof arg1 === "string") {
|
|
65
|
-
// normal constructor
|
|
66
|
-
(0, core_bentley_1.assert)(arg2 instanceof Model_1.Model);
|
|
67
|
-
this.topElement = arg1;
|
|
68
|
-
this.path.push(this.enclosingModelInfo = { model: arg2, isDefinitionModel: isDefinitionModel(arg2) });
|
|
69
|
-
}
|
|
70
|
-
else if (arg1 instanceof ElementTreeWalkerScope) {
|
|
71
|
-
// copy-like constructor
|
|
72
|
-
this.topElement = arg1.topElement;
|
|
73
|
-
this.path = [...arg1.path];
|
|
74
|
-
if (typeof arg2 === "string") {
|
|
75
|
-
// with new parent
|
|
76
|
-
this.path.push(arg2);
|
|
77
|
-
this.enclosingModelInfo = arg1.enclosingModelInfo;
|
|
78
|
-
}
|
|
79
|
-
else {
|
|
80
|
-
// with new enclosing model
|
|
81
|
-
this.path.push(this.enclosingModelInfo = { model: arg2, isDefinitionModel: isDefinitionModel(arg2) });
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
throw new Error("invalid constructor signature");
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
get enclosingModel() { return this.enclosingModelInfo.model; }
|
|
89
|
-
get inDefinitionModel() { return this.enclosingModelInfo.isDefinitionModel; } // NB: this will return false for the RepositoryModel!
|
|
90
|
-
get inRepositoryModel() { return this.enclosingModelInfo.model.id === IModelDb_1.IModelDb.repositoryModelId; }
|
|
91
|
-
static createTopScope(iModel, topElementId) {
|
|
92
|
-
const topElement = iModel.elements.getElement(topElementId);
|
|
93
|
-
const topElementModel = iModel.models.getModel(topElement.model);
|
|
94
|
-
return new ElementTreeWalkerScope(topElementId, topElementModel);
|
|
95
|
-
}
|
|
96
|
-
fmtItem(v) {
|
|
97
|
-
if (typeof v === "string")
|
|
98
|
-
return `element ${v}`;
|
|
99
|
-
return `model ${v.model.id} ${v.isDefinitionModel ? "(DEFN)" : ""}`;
|
|
100
|
-
}
|
|
101
|
-
toString() {
|
|
102
|
-
return `[ ${this.path.map((v) => this.fmtItem(v)).join(" / ")} ]`;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
exports.ElementTreeWalkerScope = ElementTreeWalkerScope;
|
|
106
|
-
function fmtElement(iModel, elementId) {
|
|
107
|
-
const el = iModel.elements.getElement(elementId);
|
|
108
|
-
return `${el.id} ${el.classFullName} ${el.getDisplayLabel()}`;
|
|
109
|
-
}
|
|
110
|
-
function fmtModel(model) {
|
|
111
|
-
return `${model.id} ${model.classFullName} ${model.name}`;
|
|
112
|
-
}
|
|
113
|
-
let isTraceEnabledChecked = -1;
|
|
114
|
-
function isTraceEnabled() {
|
|
115
|
-
if (isTraceEnabledChecked === -1)
|
|
116
|
-
isTraceEnabledChecked = core_bentley_1.Logger.isEnabled(loggerCategory, core_bentley_1.LogLevel.Trace) ? 1 : 0;
|
|
117
|
-
return isTraceEnabledChecked === 1;
|
|
118
|
-
}
|
|
119
|
-
function logElement(op, iModel, elementId, scope, logChildren) {
|
|
120
|
-
if (!isTraceEnabled())
|
|
121
|
-
return;
|
|
122
|
-
core_bentley_1.Logger.logTrace(loggerCategory, `${op} ${fmtElement(iModel, elementId)} ${scope ? scope.toString() : ""}`);
|
|
123
|
-
if (logChildren)
|
|
124
|
-
iModel.elements.queryChildren(elementId).forEach((c) => logElement(" - ", iModel, c, undefined, true));
|
|
125
|
-
}
|
|
126
|
-
function logModel(op, iModel, modelId, scope, logElements) {
|
|
127
|
-
if (!isTraceEnabled())
|
|
128
|
-
return;
|
|
129
|
-
const model = iModel.models.getModel(modelId);
|
|
130
|
-
core_bentley_1.Logger.logTrace(loggerCategory, `${op} ${fmtModel(model)} ${scope ? scope.toString() : ""}`);
|
|
131
|
-
if (logElements) {
|
|
132
|
-
iModel.withPreparedStatement(`select ecinstanceid from ${Element_1.Element.classFullName} where Model.Id = ?`, (stmt) => {
|
|
133
|
-
stmt.bindId(1, modelId);
|
|
134
|
-
while (stmt.step() === core_bentley_1.DbResult.BE_SQLITE_ROW) {
|
|
135
|
-
logElement(" - ", iModel, stmt.getValue(0).getId());
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
/** Does a depth-first search on the tree defined by an element and its sub-models and children.
|
|
141
|
-
* Sub-models are visited before their modeled elements, and children are visited before their parents.
|
|
142
|
-
*
|
|
143
|
-
* The following callbacks allow the subclass to exclude elements and sub-trees from the search:
|
|
144
|
-
* * [[ElementTreeBottomUp.shouldExploreModel]], [[ElementTreeBottomUp.shouldExploreChildren]]
|
|
145
|
-
* * [[ElementTreeBottomUp.shouldVisitElement]], [[ElementTreeBottomUp.shouldVisitModel]]
|
|
146
|
-
*
|
|
147
|
-
* The [[ElementTreeBottomUp.visitElement]] and [[ElementTreeBottomUp.visitModel]] callbacks allow
|
|
148
|
-
* the subclass to process the elements and models that are encountered in the search.
|
|
149
|
-
* @beta
|
|
150
|
-
*/
|
|
151
|
-
class ElementTreeBottomUp {
|
|
152
|
-
constructor(_iModel) {
|
|
153
|
-
this._iModel = _iModel;
|
|
154
|
-
}
|
|
155
|
-
/** Return true if the search should recurse into this model */
|
|
156
|
-
shouldExploreModel(_model, _scope) { return true; }
|
|
157
|
-
/** Return true if the search should recurse into the children (if any) of this element */
|
|
158
|
-
shouldExploreChildren(_parentId, _scope) { return true; }
|
|
159
|
-
/** Return true if the search should visit this element */
|
|
160
|
-
shouldVisitElement(_elementId, _scope) { return true; }
|
|
161
|
-
/** Return true if the search should visit this model */
|
|
162
|
-
shouldVisitModel(_model, _scope) { return true; }
|
|
163
|
-
/** The main tree-walking function */
|
|
164
|
-
processElementTree(element, scope) {
|
|
165
|
-
const subModel = this._iModel.models.tryGetModel(element);
|
|
166
|
-
if (subModel !== undefined) {
|
|
167
|
-
if (this.shouldExploreModel(subModel, scope))
|
|
168
|
-
this._processSubModel(subModel, scope);
|
|
169
|
-
if (this.shouldVisitModel(subModel, scope))
|
|
170
|
-
this.visitModel(subModel, scope);
|
|
171
|
-
}
|
|
172
|
-
if (this.shouldExploreChildren(element, scope))
|
|
173
|
-
this._processChildren(element, scope);
|
|
174
|
-
if (this.shouldVisitElement(element, scope))
|
|
175
|
-
this.visitElement(element, scope);
|
|
176
|
-
}
|
|
177
|
-
/** process the children of the specified parent element */
|
|
178
|
-
_processChildren(parentElement, parentScope) {
|
|
179
|
-
const children = this._iModel.elements.queryChildren(parentElement);
|
|
180
|
-
if (children.length === 0)
|
|
181
|
-
return;
|
|
182
|
-
const childrenScope = new ElementTreeWalkerScope(parentScope, parentElement);
|
|
183
|
-
for (const childElement of children)
|
|
184
|
-
this.processElementTree(childElement, childrenScope);
|
|
185
|
-
}
|
|
186
|
-
/** process the elements in the specified model */
|
|
187
|
-
_processSubModel(model, parenScope) {
|
|
188
|
-
const scope = new ElementTreeWalkerScope(parenScope, model);
|
|
189
|
-
// Visit only the top-level parents. processElementTree will visit their children (bottom-up).
|
|
190
|
-
model.iModel.withPreparedStatement(`select ECInstanceId from bis:Element where Model.id=? and Parent.Id is null`, (stmt) => {
|
|
191
|
-
stmt.bindId(1, model.id);
|
|
192
|
-
while (stmt.step() === core_bentley_1.DbResult.BE_SQLITE_ROW) {
|
|
193
|
-
const elementId = stmt.getValue(0).getId();
|
|
194
|
-
this.processElementTree(elementId, scope);
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
exports.ElementTreeBottomUp = ElementTreeBottomUp;
|
|
200
|
-
/** Helper class that manages the deletion of definitions and subjects */
|
|
201
|
-
class SpecialElements {
|
|
202
|
-
constructor() {
|
|
203
|
-
this.definitionModels = [];
|
|
204
|
-
this.definitions = [];
|
|
205
|
-
this.subjects = [];
|
|
206
|
-
}
|
|
207
|
-
recordSpecialElement(iModel, elementId) {
|
|
208
|
-
// Defer Definitions and Subjects
|
|
209
|
-
const cls = classifyElementForPruning(iModel, elementId);
|
|
210
|
-
if (cls === ElementPruningClassification.PRUNING_CLASS_Subject) {
|
|
211
|
-
this.subjects.push(elementId);
|
|
212
|
-
return true;
|
|
213
|
-
}
|
|
214
|
-
else if (cls === ElementPruningClassification.PRUNING_CLASS_Definition) {
|
|
215
|
-
this.definitions.push(elementId);
|
|
216
|
-
return true;
|
|
217
|
-
}
|
|
218
|
-
else if (cls === ElementPruningClassification.PRUNING_CLASS_DefinitionPartition) {
|
|
219
|
-
this.definitionModels.push(elementId);
|
|
220
|
-
return true;
|
|
221
|
-
}
|
|
222
|
-
return false; // not a special element
|
|
223
|
-
}
|
|
224
|
-
/** Delete special elements - This calls Elements.deleteDefinitionElements to process the collected definition elements as a group and then
|
|
225
|
-
* calls Models.deleteModel on collected definition models. It then deletes all collected Subjects by calling Element.deleteElement on them.
|
|
226
|
-
* @note Caller must ensure that the special elements were recorded in a depth-first search.
|
|
227
|
-
*/
|
|
228
|
-
deleteSpecialElements(iModel) {
|
|
229
|
-
// It's dangerous to pass a mixture of SubCategories and Categories to deleteDefinitionElements.
|
|
230
|
-
// That function will delete the Categories first, which automatically deletes all their child
|
|
231
|
-
// SubCategories (in native code). If a SubCategory in the list is one of those children, then
|
|
232
|
-
// deleteDefinitionElements will try and fail with an exception to delete that SubCategory in a subsequent step.
|
|
233
|
-
// To work around this, we delete the SubCategories first, then everything else.
|
|
234
|
-
// A similar problem occurs when you pass other kinds of elements to deleteDefinitionElements, where some are
|
|
235
|
-
// children and others are parents. deleteDefinitionElements does not preserve the order that you specify,
|
|
236
|
-
// and it does not process children before parents.
|
|
237
|
-
for (const definitions of sortChildrenBeforeParents(iModel, this.definitions)) {
|
|
238
|
-
if (isTraceEnabled())
|
|
239
|
-
definitions.forEach((e) => logElement("try delete", iModel, e));
|
|
240
|
-
iModel.elements.deleteDefinitionElements(definitions); // will not delete definitions that are still in use.
|
|
241
|
-
}
|
|
242
|
-
for (const m of this.definitionModels) {
|
|
243
|
-
if (!isModelEmpty(iModel, m)) {
|
|
244
|
-
logModel("Model not empty - cannot delete - may contain Definitions that are still in use", iModel, m, undefined, true);
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
logModel("delete", iModel, m);
|
|
248
|
-
iModel.models.deleteModel(m);
|
|
249
|
-
iModel.elements.deleteElement(m);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
for (const e of this.subjects) {
|
|
253
|
-
if (iModel.elements.queryChildren(e).length !== 0) {
|
|
254
|
-
logElement("Subject still has children - cannot delete - may have child DefinitionModels", iModel, e, undefined, true);
|
|
255
|
-
}
|
|
256
|
-
else {
|
|
257
|
-
logElement("delete", iModel, e);
|
|
258
|
-
iModel.elements.deleteElement(e);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
/** Deletes an entire element tree, including sub-models and child elements.
|
|
264
|
-
* Items are deleted in bottom-up order. Definitions and Subjects are deleted after normal elements.
|
|
265
|
-
* Call deleteNormalElements on each tree. Then call deleteSpecialElements.
|
|
266
|
-
* @see deleteElementTree for a simple way to use this class.
|
|
267
|
-
* @beta
|
|
268
|
-
*/
|
|
269
|
-
class ElementTreeDeleter extends ElementTreeBottomUp {
|
|
270
|
-
constructor() {
|
|
271
|
-
super(...arguments);
|
|
272
|
-
this._special = new SpecialElements();
|
|
273
|
-
}
|
|
274
|
-
shouldExploreModel(_model) { return true; }
|
|
275
|
-
shouldVisitElement(_elementId) { return true; }
|
|
276
|
-
visitModel(model, _scope) {
|
|
277
|
-
if (isDefinitionModel(model))
|
|
278
|
-
return; // we recorded definition models in visitElement when we encountered the DefinitionPartition elements.
|
|
279
|
-
// visitElement has already deleted the elements in the model. So, now it's safe to delete the model itself.
|
|
280
|
-
logModel("delete", this._iModel, model.id, _scope);
|
|
281
|
-
model.delete();
|
|
282
|
-
}
|
|
283
|
-
visitElement(elementId, _scope) {
|
|
284
|
-
if (!this._special.recordSpecialElement(this._iModel, elementId)) {
|
|
285
|
-
logElement("delete", this._iModel, elementId, _scope);
|
|
286
|
-
this._iModel.elements.deleteElement(elementId);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Delete the "normal" elements and record the special elements for deferred processing.
|
|
291
|
-
* @param topElement The parent of the sub-tree to be deleted. Top element itself is also deleted.
|
|
292
|
-
* @param scope How the parent was found
|
|
293
|
-
* @see deleteSpecialElements
|
|
294
|
-
*/
|
|
295
|
-
deleteNormalElements(topElement, scope) {
|
|
296
|
-
const topScope = scope !== null && scope !== void 0 ? scope : ElementTreeWalkerScope.createTopScope(this._iModel, topElement);
|
|
297
|
-
this.processElementTree(topElement, topScope); //
|
|
298
|
-
}
|
|
299
|
-
/** Delete all special elements that were found and deferred by deleteNormalElements. Call this
|
|
300
|
-
* function once after all element trees are processed by deleteNormalElements.
|
|
301
|
-
*/
|
|
302
|
-
deleteSpecialElements() {
|
|
303
|
-
this._special.deleteSpecialElements(this._iModel);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
exports.ElementTreeDeleter = ElementTreeDeleter;
|
|
307
|
-
/** Does a breadth-first search on the tree defined by an element and its sub-models and children.
|
|
308
|
-
* Parents are visited first, then children, then sub-models.
|
|
309
|
-
* The subclass can "prune" sub-trees from the search. When a sub-tree is "pruned" the search does *not* recurse into it.
|
|
310
|
-
* If a sub-tree is not pruned, then the search does recurse into it.
|
|
311
|
-
* @beta
|
|
312
|
-
*/
|
|
313
|
-
class ElementTreeTopDown {
|
|
314
|
-
constructor(_iModel) {
|
|
315
|
-
this._iModel = _iModel;
|
|
316
|
-
}
|
|
317
|
-
/** Should the search *not* recurse into this sub-tree? */
|
|
318
|
-
shouldPrune(_elementId, _scope) { return false; }
|
|
319
|
-
processElementTree(element, scope) {
|
|
320
|
-
if (this.shouldPrune(element, scope)) {
|
|
321
|
-
this.prune(element, scope);
|
|
322
|
-
return;
|
|
323
|
-
}
|
|
324
|
-
this._processChildren(element, scope);
|
|
325
|
-
const subModel = this._iModel.models.tryGetModel(element);
|
|
326
|
-
if (subModel !== undefined) {
|
|
327
|
-
this._processSubModel(subModel, scope);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
_processChildren(element, scope) {
|
|
331
|
-
let parentScope;
|
|
332
|
-
for (const childElement of this._iModel.elements.queryChildren(element)) {
|
|
333
|
-
if (parentScope === undefined)
|
|
334
|
-
parentScope = new ElementTreeWalkerScope(scope, element);
|
|
335
|
-
this.processElementTree(childElement, parentScope);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
_processSubModel(subModel, scope) {
|
|
339
|
-
const subModelScope = new ElementTreeWalkerScope(scope, subModel);
|
|
340
|
-
// Visit only the top-level parents. processElementTree will recurse into their children.
|
|
341
|
-
this._iModel.withPreparedStatement(`select ECInstanceId from bis:Element where Model.id=? and Parent.Id is null`, (stmt) => {
|
|
342
|
-
stmt.bindId(1, subModel.id);
|
|
343
|
-
while (stmt.step() === core_bentley_1.DbResult.BE_SQLITE_ROW) {
|
|
344
|
-
const elementId = stmt.getValue(0).getId();
|
|
345
|
-
this.processElementTree(elementId, subModelScope);
|
|
346
|
-
}
|
|
347
|
-
});
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
/** Performs a breadth-first search to visit elements in top-down order.
|
|
351
|
-
* When the supplied filter function chooses an element, ElementTreeDeleter is used to delete it and its sub-tree.
|
|
352
|
-
* @beta
|
|
353
|
-
*/
|
|
354
|
-
class ElementSubTreeDeleter extends ElementTreeTopDown {
|
|
355
|
-
/** Construct an ElementSubTreeDeleter.
|
|
356
|
-
* @param iModel The iModel
|
|
357
|
-
* @param topElement Where to start the search.
|
|
358
|
-
* @param shouldPruneCb Callback that selects sub-trees that should be deleted.
|
|
359
|
-
* @see deleteElementSubTrees for a simple way to use this class.
|
|
360
|
-
*/
|
|
361
|
-
constructor(iModel, shouldPruneCb) {
|
|
362
|
-
super(iModel);
|
|
363
|
-
this._treeDeleter = new ElementTreeDeleter(this._iModel);
|
|
364
|
-
this._shouldPruneCb = shouldPruneCb;
|
|
365
|
-
}
|
|
366
|
-
shouldPrune(elementId, scope) { return this._shouldPruneCb(elementId, scope); }
|
|
367
|
-
prune(elementId, scope) {
|
|
368
|
-
this._treeDeleter.deleteNormalElements(elementId, scope);
|
|
369
|
-
}
|
|
370
|
-
/** Traverses the tree of elements beginning with the top element, and deletes all selected sub-trees.
|
|
371
|
-
* Normal elements are deleted. Any special elements that are encountered are deferred.
|
|
372
|
-
* Call deleteSpecialElementSubTrees after all top elements have been processed. */
|
|
373
|
-
deleteNormalElementSubTrees(topElement, scope) {
|
|
374
|
-
const topScope = scope !== null && scope !== void 0 ? scope : ElementTreeWalkerScope.createTopScope(this._iModel, topElement);
|
|
375
|
-
this.processElementTree(topElement, topScope); // deletes normal elements and their sub-trees, defers special elements
|
|
376
|
-
}
|
|
377
|
-
/** Delete all special elements and their sub-trees that were found in the course of processing.
|
|
378
|
-
* The sub-trees were already expanded by ElementTreeDeleter.deleteNormalElements.
|
|
379
|
-
*/
|
|
380
|
-
deleteSpecialElementSubTrees() {
|
|
381
|
-
this._treeDeleter.deleteSpecialElements();
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
exports.ElementSubTreeDeleter = ElementSubTreeDeleter;
|
|
385
|
-
/** Deletes an element tree starting with the specified top element. The top element is also deleted. Uses ElementTreeDeleter.
|
|
386
|
-
* @param iModel The iModel
|
|
387
|
-
* @param topElement The parent of the sub-tree
|
|
388
|
-
* @beta
|
|
389
|
-
*/
|
|
390
|
-
function deleteElementTree(iModel, topElement) {
|
|
391
|
-
const del = new ElementTreeDeleter(iModel);
|
|
392
|
-
del.deleteNormalElements(topElement);
|
|
393
|
-
del.deleteSpecialElements();
|
|
394
|
-
}
|
|
395
|
-
exports.deleteElementTree = deleteElementTree;
|
|
396
|
-
/** Deletes all element sub-trees that are selected by the supplied filter. Uses ElementSubTreeDeleter.
|
|
397
|
-
* If the filter selects the top element itself, then the entire tree (including the top element) is deleted.
|
|
398
|
-
* That has the same effect as calling [[deleteElementTree]] on the top element.
|
|
399
|
-
* @param iModel The iModel
|
|
400
|
-
* @param topElement Where to start the search.
|
|
401
|
-
* @param filter Callback that selects sub-trees that should be deleted.
|
|
402
|
-
* @beta
|
|
403
|
-
*/
|
|
404
|
-
function deleteElementSubTrees(iModel, topElement, filter) {
|
|
405
|
-
const del = new ElementSubTreeDeleter(iModel, filter);
|
|
406
|
-
del.deleteNormalElementSubTrees(topElement);
|
|
407
|
-
del.deleteSpecialElementSubTrees();
|
|
408
|
-
}
|
|
409
|
-
exports.deleteElementSubTrees = deleteElementSubTrees;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deleteElementSubTrees = exports.deleteElementTree = exports.ElementSubTreeDeleter = exports.ElementTreeDeleter = exports.ElementTreeBottomUp = exports.ElementTreeWalkerScope = void 0;
|
|
4
|
+
/*---------------------------------------------------------------------------------------------
|
|
5
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
6
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
7
|
+
*--------------------------------------------------------------------------------------------*/
|
|
8
|
+
/** @packageDocumentation
|
|
9
|
+
* @module Elements
|
|
10
|
+
*/
|
|
11
|
+
const core_bentley_1 = require("@itwin/core-bentley");
|
|
12
|
+
const core_common_1 = require("@itwin/core-common");
|
|
13
|
+
const BackendLoggerCategory_1 = require("./BackendLoggerCategory");
|
|
14
|
+
const Element_1 = require("./Element");
|
|
15
|
+
const IModelDb_1 = require("./IModelDb");
|
|
16
|
+
const Model_1 = require("./Model");
|
|
17
|
+
const loggerCategory = `${BackendLoggerCategory_1.BackendLoggerCategory.IModelDb}.ElementTreeWalker`;
|
|
18
|
+
function sortChildrenBeforeParents(iModel, ids) {
|
|
19
|
+
const children = [];
|
|
20
|
+
const parents = [];
|
|
21
|
+
for (const eid of ids) {
|
|
22
|
+
const parentId = iModel.elements.queryParent(eid);
|
|
23
|
+
if (parentId !== undefined && ids.includes(parentId))
|
|
24
|
+
children.push(eid);
|
|
25
|
+
else
|
|
26
|
+
parents.push(eid);
|
|
27
|
+
}
|
|
28
|
+
if (children.length === 0)
|
|
29
|
+
return [parents];
|
|
30
|
+
return [...sortChildrenBeforeParents(iModel, children), parents];
|
|
31
|
+
}
|
|
32
|
+
function isModelEmpty(iModel, modelId) {
|
|
33
|
+
return iModel.withPreparedStatement(`select count(*) from ${Element_1.Element.classFullName} where Model.Id = ?`, (stmt) => {
|
|
34
|
+
stmt.bindId(1, modelId);
|
|
35
|
+
stmt.step();
|
|
36
|
+
return stmt.getValue(0).getInteger() === 0;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function isDefinitionModel(model) {
|
|
40
|
+
return (model.id !== core_common_1.IModel.repositoryModelId) && (model instanceof Model_1.DefinitionModel);
|
|
41
|
+
}
|
|
42
|
+
var ElementPruningClassification;
|
|
43
|
+
(function (ElementPruningClassification) {
|
|
44
|
+
ElementPruningClassification[ElementPruningClassification["PRUNING_CLASS_Normal"] = 0] = "PRUNING_CLASS_Normal";
|
|
45
|
+
ElementPruningClassification[ElementPruningClassification["PRUNING_CLASS_Subject"] = 1] = "PRUNING_CLASS_Subject";
|
|
46
|
+
ElementPruningClassification[ElementPruningClassification["PRUNING_CLASS_Definition"] = 2] = "PRUNING_CLASS_Definition";
|
|
47
|
+
ElementPruningClassification[ElementPruningClassification["PRUNING_CLASS_DefinitionPartition"] = 3] = "PRUNING_CLASS_DefinitionPartition";
|
|
48
|
+
})(ElementPruningClassification || (ElementPruningClassification = {}));
|
|
49
|
+
function classifyElementForPruning(iModel, elementId) {
|
|
50
|
+
const el = iModel.elements.getElement(elementId);
|
|
51
|
+
return (el instanceof Element_1.Subject) ? ElementPruningClassification.PRUNING_CLASS_Subject :
|
|
52
|
+
(el instanceof Element_1.DefinitionElement) ? ElementPruningClassification.PRUNING_CLASS_Definition :
|
|
53
|
+
(el instanceof Element_1.DefinitionPartition) ? ElementPruningClassification.PRUNING_CLASS_DefinitionPartition :
|
|
54
|
+
ElementPruningClassification.PRUNING_CLASS_Normal;
|
|
55
|
+
}
|
|
56
|
+
/** Records the path that a tree search took to reach an element or model. This object is immutable.
|
|
57
|
+
* @beta
|
|
58
|
+
*/
|
|
59
|
+
class ElementTreeWalkerScope {
|
|
60
|
+
constructor(arg1, arg2) {
|
|
61
|
+
this.topElement = "";
|
|
62
|
+
/** path of parent elements and enclosing models */
|
|
63
|
+
this.path = [];
|
|
64
|
+
if (typeof arg1 === "string") {
|
|
65
|
+
// normal constructor
|
|
66
|
+
(0, core_bentley_1.assert)(arg2 instanceof Model_1.Model);
|
|
67
|
+
this.topElement = arg1;
|
|
68
|
+
this.path.push(this.enclosingModelInfo = { model: arg2, isDefinitionModel: isDefinitionModel(arg2) });
|
|
69
|
+
}
|
|
70
|
+
else if (arg1 instanceof ElementTreeWalkerScope) {
|
|
71
|
+
// copy-like constructor
|
|
72
|
+
this.topElement = arg1.topElement;
|
|
73
|
+
this.path = [...arg1.path];
|
|
74
|
+
if (typeof arg2 === "string") {
|
|
75
|
+
// with new parent
|
|
76
|
+
this.path.push(arg2);
|
|
77
|
+
this.enclosingModelInfo = arg1.enclosingModelInfo;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
// with new enclosing model
|
|
81
|
+
this.path.push(this.enclosingModelInfo = { model: arg2, isDefinitionModel: isDefinitionModel(arg2) });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw new Error("invalid constructor signature");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
get enclosingModel() { return this.enclosingModelInfo.model; }
|
|
89
|
+
get inDefinitionModel() { return this.enclosingModelInfo.isDefinitionModel; } // NB: this will return false for the RepositoryModel!
|
|
90
|
+
get inRepositoryModel() { return this.enclosingModelInfo.model.id === IModelDb_1.IModelDb.repositoryModelId; }
|
|
91
|
+
static createTopScope(iModel, topElementId) {
|
|
92
|
+
const topElement = iModel.elements.getElement(topElementId);
|
|
93
|
+
const topElementModel = iModel.models.getModel(topElement.model);
|
|
94
|
+
return new ElementTreeWalkerScope(topElementId, topElementModel);
|
|
95
|
+
}
|
|
96
|
+
fmtItem(v) {
|
|
97
|
+
if (typeof v === "string")
|
|
98
|
+
return `element ${v}`;
|
|
99
|
+
return `model ${v.model.id} ${v.isDefinitionModel ? "(DEFN)" : ""}`;
|
|
100
|
+
}
|
|
101
|
+
toString() {
|
|
102
|
+
return `[ ${this.path.map((v) => this.fmtItem(v)).join(" / ")} ]`;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.ElementTreeWalkerScope = ElementTreeWalkerScope;
|
|
106
|
+
function fmtElement(iModel, elementId) {
|
|
107
|
+
const el = iModel.elements.getElement(elementId);
|
|
108
|
+
return `${el.id} ${el.classFullName} ${el.getDisplayLabel()}`;
|
|
109
|
+
}
|
|
110
|
+
function fmtModel(model) {
|
|
111
|
+
return `${model.id} ${model.classFullName} ${model.name}`;
|
|
112
|
+
}
|
|
113
|
+
let isTraceEnabledChecked = -1;
|
|
114
|
+
function isTraceEnabled() {
|
|
115
|
+
if (isTraceEnabledChecked === -1)
|
|
116
|
+
isTraceEnabledChecked = core_bentley_1.Logger.isEnabled(loggerCategory, core_bentley_1.LogLevel.Trace) ? 1 : 0;
|
|
117
|
+
return isTraceEnabledChecked === 1;
|
|
118
|
+
}
|
|
119
|
+
function logElement(op, iModel, elementId, scope, logChildren) {
|
|
120
|
+
if (!isTraceEnabled())
|
|
121
|
+
return;
|
|
122
|
+
core_bentley_1.Logger.logTrace(loggerCategory, `${op} ${fmtElement(iModel, elementId)} ${scope ? scope.toString() : ""}`);
|
|
123
|
+
if (logChildren)
|
|
124
|
+
iModel.elements.queryChildren(elementId).forEach((c) => logElement(" - ", iModel, c, undefined, true));
|
|
125
|
+
}
|
|
126
|
+
function logModel(op, iModel, modelId, scope, logElements) {
|
|
127
|
+
if (!isTraceEnabled())
|
|
128
|
+
return;
|
|
129
|
+
const model = iModel.models.getModel(modelId);
|
|
130
|
+
core_bentley_1.Logger.logTrace(loggerCategory, `${op} ${fmtModel(model)} ${scope ? scope.toString() : ""}`);
|
|
131
|
+
if (logElements) {
|
|
132
|
+
iModel.withPreparedStatement(`select ecinstanceid from ${Element_1.Element.classFullName} where Model.Id = ?`, (stmt) => {
|
|
133
|
+
stmt.bindId(1, modelId);
|
|
134
|
+
while (stmt.step() === core_bentley_1.DbResult.BE_SQLITE_ROW) {
|
|
135
|
+
logElement(" - ", iModel, stmt.getValue(0).getId());
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/** Does a depth-first search on the tree defined by an element and its sub-models and children.
|
|
141
|
+
* Sub-models are visited before their modeled elements, and children are visited before their parents.
|
|
142
|
+
*
|
|
143
|
+
* The following callbacks allow the subclass to exclude elements and sub-trees from the search:
|
|
144
|
+
* * [[ElementTreeBottomUp.shouldExploreModel]], [[ElementTreeBottomUp.shouldExploreChildren]]
|
|
145
|
+
* * [[ElementTreeBottomUp.shouldVisitElement]], [[ElementTreeBottomUp.shouldVisitModel]]
|
|
146
|
+
*
|
|
147
|
+
* The [[ElementTreeBottomUp.visitElement]] and [[ElementTreeBottomUp.visitModel]] callbacks allow
|
|
148
|
+
* the subclass to process the elements and models that are encountered in the search.
|
|
149
|
+
* @beta
|
|
150
|
+
*/
|
|
151
|
+
class ElementTreeBottomUp {
|
|
152
|
+
constructor(_iModel) {
|
|
153
|
+
this._iModel = _iModel;
|
|
154
|
+
}
|
|
155
|
+
/** Return true if the search should recurse into this model */
|
|
156
|
+
shouldExploreModel(_model, _scope) { return true; }
|
|
157
|
+
/** Return true if the search should recurse into the children (if any) of this element */
|
|
158
|
+
shouldExploreChildren(_parentId, _scope) { return true; }
|
|
159
|
+
/** Return true if the search should visit this element */
|
|
160
|
+
shouldVisitElement(_elementId, _scope) { return true; }
|
|
161
|
+
/** Return true if the search should visit this model */
|
|
162
|
+
shouldVisitModel(_model, _scope) { return true; }
|
|
163
|
+
/** The main tree-walking function */
|
|
164
|
+
processElementTree(element, scope) {
|
|
165
|
+
const subModel = this._iModel.models.tryGetModel(element);
|
|
166
|
+
if (subModel !== undefined) {
|
|
167
|
+
if (this.shouldExploreModel(subModel, scope))
|
|
168
|
+
this._processSubModel(subModel, scope);
|
|
169
|
+
if (this.shouldVisitModel(subModel, scope))
|
|
170
|
+
this.visitModel(subModel, scope);
|
|
171
|
+
}
|
|
172
|
+
if (this.shouldExploreChildren(element, scope))
|
|
173
|
+
this._processChildren(element, scope);
|
|
174
|
+
if (this.shouldVisitElement(element, scope))
|
|
175
|
+
this.visitElement(element, scope);
|
|
176
|
+
}
|
|
177
|
+
/** process the children of the specified parent element */
|
|
178
|
+
_processChildren(parentElement, parentScope) {
|
|
179
|
+
const children = this._iModel.elements.queryChildren(parentElement);
|
|
180
|
+
if (children.length === 0)
|
|
181
|
+
return;
|
|
182
|
+
const childrenScope = new ElementTreeWalkerScope(parentScope, parentElement);
|
|
183
|
+
for (const childElement of children)
|
|
184
|
+
this.processElementTree(childElement, childrenScope);
|
|
185
|
+
}
|
|
186
|
+
/** process the elements in the specified model */
|
|
187
|
+
_processSubModel(model, parenScope) {
|
|
188
|
+
const scope = new ElementTreeWalkerScope(parenScope, model);
|
|
189
|
+
// Visit only the top-level parents. processElementTree will visit their children (bottom-up).
|
|
190
|
+
model.iModel.withPreparedStatement(`select ECInstanceId from bis:Element where Model.id=? and Parent.Id is null`, (stmt) => {
|
|
191
|
+
stmt.bindId(1, model.id);
|
|
192
|
+
while (stmt.step() === core_bentley_1.DbResult.BE_SQLITE_ROW) {
|
|
193
|
+
const elementId = stmt.getValue(0).getId();
|
|
194
|
+
this.processElementTree(elementId, scope);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
exports.ElementTreeBottomUp = ElementTreeBottomUp;
|
|
200
|
+
/** Helper class that manages the deletion of definitions and subjects */
|
|
201
|
+
class SpecialElements {
|
|
202
|
+
constructor() {
|
|
203
|
+
this.definitionModels = [];
|
|
204
|
+
this.definitions = [];
|
|
205
|
+
this.subjects = [];
|
|
206
|
+
}
|
|
207
|
+
recordSpecialElement(iModel, elementId) {
|
|
208
|
+
// Defer Definitions and Subjects
|
|
209
|
+
const cls = classifyElementForPruning(iModel, elementId);
|
|
210
|
+
if (cls === ElementPruningClassification.PRUNING_CLASS_Subject) {
|
|
211
|
+
this.subjects.push(elementId);
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
else if (cls === ElementPruningClassification.PRUNING_CLASS_Definition) {
|
|
215
|
+
this.definitions.push(elementId);
|
|
216
|
+
return true;
|
|
217
|
+
}
|
|
218
|
+
else if (cls === ElementPruningClassification.PRUNING_CLASS_DefinitionPartition) {
|
|
219
|
+
this.definitionModels.push(elementId);
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
return false; // not a special element
|
|
223
|
+
}
|
|
224
|
+
/** Delete special elements - This calls Elements.deleteDefinitionElements to process the collected definition elements as a group and then
|
|
225
|
+
* calls Models.deleteModel on collected definition models. It then deletes all collected Subjects by calling Element.deleteElement on them.
|
|
226
|
+
* @note Caller must ensure that the special elements were recorded in a depth-first search.
|
|
227
|
+
*/
|
|
228
|
+
deleteSpecialElements(iModel) {
|
|
229
|
+
// It's dangerous to pass a mixture of SubCategories and Categories to deleteDefinitionElements.
|
|
230
|
+
// That function will delete the Categories first, which automatically deletes all their child
|
|
231
|
+
// SubCategories (in native code). If a SubCategory in the list is one of those children, then
|
|
232
|
+
// deleteDefinitionElements will try and fail with an exception to delete that SubCategory in a subsequent step.
|
|
233
|
+
// To work around this, we delete the SubCategories first, then everything else.
|
|
234
|
+
// A similar problem occurs when you pass other kinds of elements to deleteDefinitionElements, where some are
|
|
235
|
+
// children and others are parents. deleteDefinitionElements does not preserve the order that you specify,
|
|
236
|
+
// and it does not process children before parents.
|
|
237
|
+
for (const definitions of sortChildrenBeforeParents(iModel, this.definitions)) {
|
|
238
|
+
if (isTraceEnabled())
|
|
239
|
+
definitions.forEach((e) => logElement("try delete", iModel, e));
|
|
240
|
+
iModel.elements.deleteDefinitionElements(definitions); // will not delete definitions that are still in use.
|
|
241
|
+
}
|
|
242
|
+
for (const m of this.definitionModels) {
|
|
243
|
+
if (!isModelEmpty(iModel, m)) {
|
|
244
|
+
logModel("Model not empty - cannot delete - may contain Definitions that are still in use", iModel, m, undefined, true);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
logModel("delete", iModel, m);
|
|
248
|
+
iModel.models.deleteModel(m);
|
|
249
|
+
iModel.elements.deleteElement(m);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
for (const e of this.subjects) {
|
|
253
|
+
if (iModel.elements.queryChildren(e).length !== 0) {
|
|
254
|
+
logElement("Subject still has children - cannot delete - may have child DefinitionModels", iModel, e, undefined, true);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
logElement("delete", iModel, e);
|
|
258
|
+
iModel.elements.deleteElement(e);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** Deletes an entire element tree, including sub-models and child elements.
|
|
264
|
+
* Items are deleted in bottom-up order. Definitions and Subjects are deleted after normal elements.
|
|
265
|
+
* Call deleteNormalElements on each tree. Then call deleteSpecialElements.
|
|
266
|
+
* @see deleteElementTree for a simple way to use this class.
|
|
267
|
+
* @beta
|
|
268
|
+
*/
|
|
269
|
+
class ElementTreeDeleter extends ElementTreeBottomUp {
|
|
270
|
+
constructor() {
|
|
271
|
+
super(...arguments);
|
|
272
|
+
this._special = new SpecialElements();
|
|
273
|
+
}
|
|
274
|
+
shouldExploreModel(_model) { return true; }
|
|
275
|
+
shouldVisitElement(_elementId) { return true; }
|
|
276
|
+
visitModel(model, _scope) {
|
|
277
|
+
if (isDefinitionModel(model))
|
|
278
|
+
return; // we recorded definition models in visitElement when we encountered the DefinitionPartition elements.
|
|
279
|
+
// visitElement has already deleted the elements in the model. So, now it's safe to delete the model itself.
|
|
280
|
+
logModel("delete", this._iModel, model.id, _scope);
|
|
281
|
+
model.delete();
|
|
282
|
+
}
|
|
283
|
+
visitElement(elementId, _scope) {
|
|
284
|
+
if (!this._special.recordSpecialElement(this._iModel, elementId)) {
|
|
285
|
+
logElement("delete", this._iModel, elementId, _scope);
|
|
286
|
+
this._iModel.elements.deleteElement(elementId);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Delete the "normal" elements and record the special elements for deferred processing.
|
|
291
|
+
* @param topElement The parent of the sub-tree to be deleted. Top element itself is also deleted.
|
|
292
|
+
* @param scope How the parent was found
|
|
293
|
+
* @see deleteSpecialElements
|
|
294
|
+
*/
|
|
295
|
+
deleteNormalElements(topElement, scope) {
|
|
296
|
+
const topScope = scope !== null && scope !== void 0 ? scope : ElementTreeWalkerScope.createTopScope(this._iModel, topElement);
|
|
297
|
+
this.processElementTree(topElement, topScope); //
|
|
298
|
+
}
|
|
299
|
+
/** Delete all special elements that were found and deferred by deleteNormalElements. Call this
|
|
300
|
+
* function once after all element trees are processed by deleteNormalElements.
|
|
301
|
+
*/
|
|
302
|
+
deleteSpecialElements() {
|
|
303
|
+
this._special.deleteSpecialElements(this._iModel);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
exports.ElementTreeDeleter = ElementTreeDeleter;
|
|
307
|
+
/** Does a breadth-first search on the tree defined by an element and its sub-models and children.
|
|
308
|
+
* Parents are visited first, then children, then sub-models.
|
|
309
|
+
* The subclass can "prune" sub-trees from the search. When a sub-tree is "pruned" the search does *not* recurse into it.
|
|
310
|
+
* If a sub-tree is not pruned, then the search does recurse into it.
|
|
311
|
+
* @beta
|
|
312
|
+
*/
|
|
313
|
+
class ElementTreeTopDown {
|
|
314
|
+
constructor(_iModel) {
|
|
315
|
+
this._iModel = _iModel;
|
|
316
|
+
}
|
|
317
|
+
/** Should the search *not* recurse into this sub-tree? */
|
|
318
|
+
shouldPrune(_elementId, _scope) { return false; }
|
|
319
|
+
processElementTree(element, scope) {
|
|
320
|
+
if (this.shouldPrune(element, scope)) {
|
|
321
|
+
this.prune(element, scope);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
this._processChildren(element, scope);
|
|
325
|
+
const subModel = this._iModel.models.tryGetModel(element);
|
|
326
|
+
if (subModel !== undefined) {
|
|
327
|
+
this._processSubModel(subModel, scope);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
_processChildren(element, scope) {
|
|
331
|
+
let parentScope;
|
|
332
|
+
for (const childElement of this._iModel.elements.queryChildren(element)) {
|
|
333
|
+
if (parentScope === undefined)
|
|
334
|
+
parentScope = new ElementTreeWalkerScope(scope, element);
|
|
335
|
+
this.processElementTree(childElement, parentScope);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
_processSubModel(subModel, scope) {
|
|
339
|
+
const subModelScope = new ElementTreeWalkerScope(scope, subModel);
|
|
340
|
+
// Visit only the top-level parents. processElementTree will recurse into their children.
|
|
341
|
+
this._iModel.withPreparedStatement(`select ECInstanceId from bis:Element where Model.id=? and Parent.Id is null`, (stmt) => {
|
|
342
|
+
stmt.bindId(1, subModel.id);
|
|
343
|
+
while (stmt.step() === core_bentley_1.DbResult.BE_SQLITE_ROW) {
|
|
344
|
+
const elementId = stmt.getValue(0).getId();
|
|
345
|
+
this.processElementTree(elementId, subModelScope);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/** Performs a breadth-first search to visit elements in top-down order.
|
|
351
|
+
* When the supplied filter function chooses an element, ElementTreeDeleter is used to delete it and its sub-tree.
|
|
352
|
+
* @beta
|
|
353
|
+
*/
|
|
354
|
+
class ElementSubTreeDeleter extends ElementTreeTopDown {
|
|
355
|
+
/** Construct an ElementSubTreeDeleter.
|
|
356
|
+
* @param iModel The iModel
|
|
357
|
+
* @param topElement Where to start the search.
|
|
358
|
+
* @param shouldPruneCb Callback that selects sub-trees that should be deleted.
|
|
359
|
+
* @see deleteElementSubTrees for a simple way to use this class.
|
|
360
|
+
*/
|
|
361
|
+
constructor(iModel, shouldPruneCb) {
|
|
362
|
+
super(iModel);
|
|
363
|
+
this._treeDeleter = new ElementTreeDeleter(this._iModel);
|
|
364
|
+
this._shouldPruneCb = shouldPruneCb;
|
|
365
|
+
}
|
|
366
|
+
shouldPrune(elementId, scope) { return this._shouldPruneCb(elementId, scope); }
|
|
367
|
+
prune(elementId, scope) {
|
|
368
|
+
this._treeDeleter.deleteNormalElements(elementId, scope);
|
|
369
|
+
}
|
|
370
|
+
/** Traverses the tree of elements beginning with the top element, and deletes all selected sub-trees.
|
|
371
|
+
* Normal elements are deleted. Any special elements that are encountered are deferred.
|
|
372
|
+
* Call deleteSpecialElementSubTrees after all top elements have been processed. */
|
|
373
|
+
deleteNormalElementSubTrees(topElement, scope) {
|
|
374
|
+
const topScope = scope !== null && scope !== void 0 ? scope : ElementTreeWalkerScope.createTopScope(this._iModel, topElement);
|
|
375
|
+
this.processElementTree(topElement, topScope); // deletes normal elements and their sub-trees, defers special elements
|
|
376
|
+
}
|
|
377
|
+
/** Delete all special elements and their sub-trees that were found in the course of processing.
|
|
378
|
+
* The sub-trees were already expanded by ElementTreeDeleter.deleteNormalElements.
|
|
379
|
+
*/
|
|
380
|
+
deleteSpecialElementSubTrees() {
|
|
381
|
+
this._treeDeleter.deleteSpecialElements();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
exports.ElementSubTreeDeleter = ElementSubTreeDeleter;
|
|
385
|
+
/** Deletes an element tree starting with the specified top element. The top element is also deleted. Uses ElementTreeDeleter.
|
|
386
|
+
* @param iModel The iModel
|
|
387
|
+
* @param topElement The parent of the sub-tree
|
|
388
|
+
* @beta
|
|
389
|
+
*/
|
|
390
|
+
function deleteElementTree(iModel, topElement) {
|
|
391
|
+
const del = new ElementTreeDeleter(iModel);
|
|
392
|
+
del.deleteNormalElements(topElement);
|
|
393
|
+
del.deleteSpecialElements();
|
|
394
|
+
}
|
|
395
|
+
exports.deleteElementTree = deleteElementTree;
|
|
396
|
+
/** Deletes all element sub-trees that are selected by the supplied filter. Uses ElementSubTreeDeleter.
|
|
397
|
+
* If the filter selects the top element itself, then the entire tree (including the top element) is deleted.
|
|
398
|
+
* That has the same effect as calling [[deleteElementTree]] on the top element.
|
|
399
|
+
* @param iModel The iModel
|
|
400
|
+
* @param topElement Where to start the search.
|
|
401
|
+
* @param filter Callback that selects sub-trees that should be deleted.
|
|
402
|
+
* @beta
|
|
403
|
+
*/
|
|
404
|
+
function deleteElementSubTrees(iModel, topElement, filter) {
|
|
405
|
+
const del = new ElementSubTreeDeleter(iModel, filter);
|
|
406
|
+
del.deleteNormalElementSubTrees(topElement);
|
|
407
|
+
del.deleteSpecialElementSubTrees();
|
|
408
|
+
}
|
|
409
|
+
exports.deleteElementSubTrees = deleteElementSubTrees;
|
|
410
410
|
//# sourceMappingURL=ElementTreeWalker.js.map
|