Allow element to change its parent or model or both#9303
Conversation
…arify locking requirements and callback behavior
…ents between models and parents
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…e checks and improve error handling
… method in IModelDb namespace
…ication and update documentation
…larify parameter options
|
Didn't we already deal with this in a past PR? I distinctly remember telling whomever was working on it then to NOT call this "move" - that is the term we use for geometric location. It will confuse everyone! At the time, i remember discussing why "move tree" is a bad idea. What brings this up again? |
|
…changeElementModel - Added `EditTxn.changeElementParent` and `EditTxn.changeElementModel` methods for changing the parent and model of leaf elements, respectively. - Implemented `IModelDb.Elements.changeElementParent` and `IModelDb.Elements.changeElementModel` for recursively moving elements and their subtrees. - Removed the deprecated `EditTxn.moveElement` and related tests. - Updated documentation to reflect the new methods and their usage.
| const sourceModel = iModel.models.getModel(sourceModelId); | ||
| const targetModel = iModel.models.getModel(targetModelId); | ||
| if (sourceModel.classFullName !== targetModel.classFullName) | ||
| ITwinError.throwError({ message: `cannot move element from model of type '${sourceModel.classFullName}' to model of type '${targetModel.classFullName}'`, iTwinErrorId: { scope: "imodel", key: "invalid-arguments" } }); |
There was a problem hiding this comment.
Make a new ITwinError interface for this so callers can know what errors to expect.
There was a problem hiding this comment.
I have removed the recursive version of this function from IModelDb.
| * @throws [[ITwinError]] if the operation fails (e.g., model type mismatch, code scope conflict). | ||
| * @beta | ||
| */ | ||
| public changeElementParent(props: ChangeElementParentProps): void { |
There was a problem hiding this comment.
This method should be on EditTxn, not here. It should not commit a transaction
There was a problem hiding this comment.
Frankly, I don't understand why there should be 2 methods (single element vs. element+children). Why is that necessary? But you definitely should not have an API that commits its changes.
There was a problem hiding this comment.
I have removed the recursive version of this function from IModelDb.
|
This pull request is now in conflicts. Could you fix it @khanaffan? 🙏 |
|
@copilot resolve the merge conflicts in this pull request |
Co-authored-by: khanaffan <29756942+khanaffan@users.noreply.github.com>
Merge conflicts resolved in commit eee59c2. The two conflicts were:
|
…hods to change parent and model of leaf elements without deletion. Updated documentation for clarity on usage and constraints.
|
This pull request is now in conflicts. Could you fix it @khanaffan? 🙏 |
imodel-native: iTwin/imodel-native#1428
Add
changeElementParentandchangeElementModelmethods to@itwin/core-backendAdds new
@betaAPIs for moving elements between models and/or parents without deleting and re-inserting them. The native implementation automatically handles moving element subtrees (assemblies) — all descendants are moved along with the parent element.Changes
EditTxn.changeElementParent— changes the parent of an element. If the new parent is in a different model, the element's model changes as well. When called on an element with children, all descendants are automatically moved as well (handled by the native implementation). Enforces model type matching, channel verification, and lock checks.EditTxn.changeElementModel— changes the model of an element, making it a root element (no parent) in the new model. When called on an element with children, all descendants are automatically moved as well (handled by the native implementation). Enforces model type matching, channel verification, and lock checks.IModelDb.Elements.changeElementParent— deprecated convenience wrapper that delegates to the implicit transaction. UseEditTxn.changeElementParentinstead within an explicit EditTxn scope.IModelDb.Elements.changeElementModel— deprecated convenience wrapper that delegates to the implicit transaction. UseEditTxn.changeElementModelinstead within an explicit EditTxn scope.ChangeElementParentProps/ChangeElementModelProps— interfaces specifying move parameters (element id, target parent/model).Code scope restrictions
Blocked scopes (will throw):
Model-scoped code — code uniqueness is tied to the source model; moving across models would break uniqueness guarantees.ParentElement-scoped code — code scope is invalidated by reparenting; the scope reference becomes stale.Allowed scopes (move proceeds):
Repository-scoped code — unique across the entire iModel, unaffected by model or parent changes.RelatedElement-scoped code — scope element is independent of the parent/model hierarchy.For elements with blocked code scopes, use delete+insert instead of move.
Validation
ChangeElementParentModel.test.ts) covering single-element moves, subtree moves (assemblies), model type mismatch, circular dependency rejection, self-parenting rejection, blocked code scopes (Model-scoped, ParentElement-scoped), allowed code scopes (Repository-scoped, RelatedElement-scoped, empty), and channel verification.