text_document_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 owner_id: Option<EntityId>,
68 index: i32,
69 old_tree_snapshot: Option<EntityTreeSnapshot>,
70 existing_child_ids: Vec<EntityId>,
72 displaced_children_snapshot: Option<EntityTreeSnapshot>,
73 previous_owner_relationship_ids: Option<Vec<EntityId>>,
75}
76
77impl<F: OwnedWriteUoWFactory> UndoableCreateUseCase<F> {
78 pub fn new(uow_factory: F, strategy: OwnerStrategy) -> Self {
79 UndoableCreateUseCase {
80 uow_factory,
81 strategy,
82 created_entities: Vec::new(),
83 owner_id: None,
84 index: -1,
85 old_tree_snapshot: None,
86 existing_child_ids: Vec::new(),
87 displaced_children_snapshot: None,
88 previous_owner_relationship_ids: None,
89 }
90 }
91
92 pub fn execute(
93 &mut self,
94 entity: &F::Entity,
95 owner_id: EntityId,
96 index: i32,
97 ) -> Result<F::Entity> {
98 let results = self.execute_multi(std::slice::from_ref(entity), owner_id, index)?;
99 results
100 .into_iter()
101 .next()
102 .ok_or_else(|| anyhow::anyhow!("Create returned empty"))
103 }
104
105 pub fn execute_multi(
106 &mut self,
107 entities: &[F::Entity],
108 owner_id: EntityId,
109 index: i32,
110 ) -> Result<Vec<F::Entity>> {
111 let mut uow = self.uow_factory.create();
112 uow.begin_transaction()?;
113
114 self.owner_id = Some(owner_id);
115 self.index = index;
116
117 match self.strategy {
118 OwnerStrategy::Replacing => {
119 self.existing_child_ids = uow.get_relationships_from_owner(&owner_id)?;
120 if !self.existing_child_ids.is_empty() {
121 self.displaced_children_snapshot =
122 Some(uow.snapshot(&self.existing_child_ids)?);
123 }
124 }
125 OwnerStrategy::Appending => {
126 self.previous_owner_relationship_ids =
127 Some(uow.get_relationships_from_owner(&owner_id)?);
128 }
129 }
130
131 let created = uow.create_multi(entities, owner_id, index)?;
132 uow.commit()?;
133
134 self.created_entities = created.clone();
135 Ok(created)
136 }
137}
138
139impl<F: OwnedWriteUoWFactory + Send + 'static> UndoRedoCommand for UndoableCreateUseCase<F>
140where
141 F::Entity: 'static,
142{
143 fn undo(&mut self) -> Result<()> {
144 if !self.created_entities.is_empty() {
145 let owner_id = self.owner_id.expect("owner_id not set");
146 let ids_to_remove: Vec<EntityId> =
147 self.created_entities.iter().map(|e| e.id()).collect();
148 let mut uow = self.uow_factory.create();
149 uow.begin_transaction()?;
150
151 self.old_tree_snapshot = Some(uow.snapshot(&ids_to_remove)?);
152 uow.remove_multi(&ids_to_remove)?;
153
154 match self.strategy {
155 OwnerStrategy::Replacing => {
156 if let Some(ref snap) = self.displaced_children_snapshot {
157 uow.restore(snap)?;
158 uow.set_relationships_in_owner(&owner_id, &self.existing_child_ids)?;
159 } else {
160 uow.set_relationships_in_owner(&owner_id, &[])?;
161 }
162 }
163 OwnerStrategy::Appending => {
164 if let Some(ref prev_ids) = self.previous_owner_relationship_ids {
165 uow.set_relationships_in_owner(&owner_id, prev_ids)?;
166 }
167 }
168 }
169
170 uow.commit()?;
171 }
172 Ok(())
173 }
174
175 fn redo(&mut self) -> Result<()> {
176 if let Some(ref snapshot) = self.old_tree_snapshot {
177 let owner_id = self.owner_id.expect("owner_id not set");
178 let mut uow = self.uow_factory.create();
179 uow.begin_transaction()?;
180
181 match self.strategy {
182 OwnerStrategy::Replacing => {
183 if !self.existing_child_ids.is_empty() {
184 self.displaced_children_snapshot =
185 Some(uow.snapshot(&self.existing_child_ids)?);
186 uow.remove_multi(&self.existing_child_ids)?;
187 }
188 uow.restore(snapshot)?;
189 let created_ids: Vec<EntityId> =
190 self.created_entities.iter().map(|e| e.id()).collect();
191 uow.set_relationships_in_owner(&owner_id, &created_ids)?;
192 }
193 OwnerStrategy::Appending => {
194 uow.restore(snapshot)?;
195 if let Some(ref prev_ids) = self.previous_owner_relationship_ids {
196 let mut redo_junction = prev_ids.clone();
197 let created_ids: Vec<EntityId> =
198 self.created_entities.iter().map(|e| e.id()).collect();
199 if self.index >= 0 && (self.index as usize) < redo_junction.len() {
200 for (i, id) in created_ids.iter().enumerate() {
201 redo_junction.insert(self.index as usize + i, *id);
202 }
203 } else {
204 redo_junction.extend(created_ids.iter());
205 }
206 uow.set_relationships_in_owner(&owner_id, &redo_junction)?;
207 }
208 }
209 }
210
211 uow.commit()?;
212 }
213 Ok(())
214 }
215
216 fn as_any(&self) -> &dyn Any {
217 self
218 }
219}