common/direct_access/use_cases/
create.rs1use super::traits::OwnedWriteUoWFactory;
4use crate::snapshot::EntityTreeSnapshot;
5use crate::types::{EntityId, HasId};
6use crate::undo_redo::UndoRedoCommand;
7use anyhow::{Ok, Result};
8use std::any::Any;
9
10#[derive(Debug, Clone, Copy, PartialEq)]
12pub enum OwnerStrategy {
13 Replacing,
15 Appending,
17}
18
19pub struct CreateUseCase<F: OwnedWriteUoWFactory> {
24 uow_factory: F,
25}
26
27impl<F: OwnedWriteUoWFactory> CreateUseCase<F> {
28 pub fn new(uow_factory: F) -> Self {
29 CreateUseCase { uow_factory }
30 }
31
32 pub fn execute(
33 &mut self,
34 entity: &F::Entity,
35 owner_id: EntityId,
36 index: i32,
37 ) -> Result<F::Entity> {
38 let results = self.execute_multi(std::slice::from_ref(entity), owner_id, index)?;
39 results
40 .into_iter()
41 .next()
42 .ok_or_else(|| anyhow::anyhow!("Create returned empty"))
43 }
44
45 pub fn execute_multi(
46 &mut self,
47 entities: &[F::Entity],
48 owner_id: EntityId,
49 index: i32,
50 ) -> Result<Vec<F::Entity>> {
51 let mut uow = self.uow_factory.create();
52 uow.begin_transaction()?;
53 let created = uow.create_multi(entities, owner_id, index)?;
54 uow.commit()?;
55 Ok(created)
56 }
57}
58
59pub struct UndoableCreateUseCase<F: OwnedWriteUoWFactory> {
64 uow_factory: F,
65 strategy: OwnerStrategy,
66 created_entities: Vec<F::Entity>,
67 old_tree_snapshot: Option<EntityTreeSnapshot>,
68 existing_child_ids: Vec<EntityId>,
71 displaced_children_snapshot: Option<EntityTreeSnapshot>,
72}
73
74impl<F: OwnedWriteUoWFactory> UndoableCreateUseCase<F> {
75 pub fn new(uow_factory: F, strategy: OwnerStrategy) -> Self {
76 UndoableCreateUseCase {
77 uow_factory,
78 strategy,
79 created_entities: Vec::new(),
80 old_tree_snapshot: None,
81 existing_child_ids: Vec::new(),
82 displaced_children_snapshot: None,
83 }
84 }
85
86 pub fn execute(
87 &mut self,
88 entity: &F::Entity,
89 owner_id: EntityId,
90 index: i32,
91 ) -> Result<F::Entity> {
92 let results = self.execute_multi(std::slice::from_ref(entity), owner_id, index)?;
93 results
94 .into_iter()
95 .next()
96 .ok_or_else(|| anyhow::anyhow!("Create returned empty"))
97 }
98
99 pub fn execute_multi(
100 &mut self,
101 entities: &[F::Entity],
102 owner_id: EntityId,
103 index: i32,
104 ) -> Result<Vec<F::Entity>> {
105 let mut uow = self.uow_factory.create();
106 uow.begin_transaction()?;
107
108 if let OwnerStrategy::Replacing = self.strategy {
111 self.existing_child_ids = uow.get_relationships_from_owner(&owner_id)?;
112 if !self.existing_child_ids.is_empty() {
113 self.displaced_children_snapshot = Some(uow.snapshot(&self.existing_child_ids)?);
114 }
115 }
116
117 let created = uow.create_multi(entities, owner_id, index)?;
118 uow.commit()?;
119
120 self.created_entities = created.clone();
121 Ok(created)
122 }
123}
124
125impl<F: OwnedWriteUoWFactory + Send + 'static> UndoRedoCommand for UndoableCreateUseCase<F>
126where
127 F::Entity: 'static,
128{
129 fn undo(&mut self) -> Result<()> {
130 if !self.created_entities.is_empty() {
131 let ids_to_remove: Vec<EntityId> =
132 self.created_entities.iter().map(|e| e.id()).collect();
133 let mut uow = self.uow_factory.create();
134 uow.begin_transaction()?;
135
136 self.old_tree_snapshot = Some(uow.snapshot(&ids_to_remove)?);
140 uow.remove_multi(&ids_to_remove)?;
141
142 if let OwnerStrategy::Replacing = self.strategy
145 && let Some(ref snap) = self.displaced_children_snapshot
146 {
147 uow.restore(snap)?;
148 }
149
150 uow.commit()?;
151 }
152 Ok(())
153 }
154
155 fn redo(&mut self) -> Result<()> {
156 if let Some(ref snapshot) = self.old_tree_snapshot {
157 let mut uow = self.uow_factory.create();
158 uow.begin_transaction()?;
159
160 if let OwnerStrategy::Replacing = self.strategy
162 && !self.existing_child_ids.is_empty()
163 {
164 self.displaced_children_snapshot = Some(uow.snapshot(&self.existing_child_ids)?);
165 uow.remove_multi(&self.existing_child_ids)?;
166 }
167
168 uow.restore(snapshot)?;
170
171 uow.commit()?;
172 }
173 Ok(())
174 }
175
176 fn as_any(&self) -> &dyn Any {
177 self
178 }
179}