text_document_direct_access/list/
list_controller.rs1use super::{
4 dtos::{CreateListDto, ListDto, UpdateListDto},
5 units_of_work::{ListReadUoWFactory, ListWriteUoWFactory},
6};
7use anyhow::{Ok, Result};
8use common::direct_access::use_cases;
9use common::undo_redo::UndoRedoManager;
10use common::{database::db_context::DbContext, event::EventHub, types::EntityId};
11use std::sync::Arc;
12
13pub fn create_orphan(
14 db_context: &DbContext,
15 event_hub: &Arc<EventHub>,
16 undo_redo_manager: &mut UndoRedoManager,
17 stack_id: Option<u64>,
18 entity: &CreateListDto,
19) -> Result<ListDto> {
20 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
21 let mut uc = use_cases::UndoableCreateOrphanUseCase::new(uow_factory);
22 let entity_in: common::entities::List = entity.into();
23 let result = uc.execute(&entity_in)?;
24 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
25 Ok(result.into())
26}
27
28pub fn create_orphan_multi(
29 db_context: &DbContext,
30 event_hub: &Arc<EventHub>,
31 undo_redo_manager: &mut UndoRedoManager,
32 stack_id: Option<u64>,
33 entities: &[CreateListDto],
34) -> Result<Vec<ListDto>> {
35 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
36 let entities_in: Vec<common::entities::List> = entities.iter().map(|dto| dto.into()).collect();
37 let mut uc = use_cases::UndoableCreateOrphanUseCase::new(uow_factory);
38 let result = uc.execute_multi(&entities_in)?;
39 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
40 Ok(result.into_iter().map(|e| e.into()).collect())
41}
42
43pub fn create(
44 db_context: &DbContext,
45 event_hub: &Arc<EventHub>,
46 undo_redo_manager: &mut UndoRedoManager,
47 stack_id: Option<u64>,
48 entity: &CreateListDto,
49 owner_id: EntityId,
50 index: i32,
51) -> Result<ListDto> {
52 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
53 let entity_in: common::entities::List = entity.into();
54 let strategy = use_cases::OwnerStrategy::Appending;
55 let mut uc = use_cases::UndoableCreateUseCase::new(uow_factory, strategy);
56 let result = uc.execute(&entity_in, owner_id, index)?;
57 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
58 Ok(result.into())
59}
60
61pub fn create_multi(
62 db_context: &DbContext,
63 event_hub: &Arc<EventHub>,
64 undo_redo_manager: &mut UndoRedoManager,
65 stack_id: Option<u64>,
66 entities: &[CreateListDto],
67 owner_id: EntityId,
68 index: i32,
69) -> Result<Vec<ListDto>> {
70 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
71 let entities_in: Vec<common::entities::List> = entities.iter().map(|dto| dto.into()).collect();
72 let strategy = use_cases::OwnerStrategy::Appending;
73 let mut uc = use_cases::UndoableCreateUseCase::new(uow_factory, strategy);
74 let result = uc.execute_multi(&entities_in, owner_id, index)?;
75 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
76 Ok(result.into_iter().map(|e| e.into()).collect())
77}
78
79pub fn get(db_context: &DbContext, id: &EntityId) -> Result<Option<ListDto>> {
80 let uow_factory = ListReadUoWFactory::new(db_context);
81 let uc = use_cases::GetUseCase::new(uow_factory);
82 Ok(uc.execute(id)?.map(|e| e.into()))
83}
84
85pub fn get_all(db_context: &DbContext) -> Result<Vec<ListDto>> {
86 let uow_factory = ListReadUoWFactory::new(db_context);
87 let uc = use_cases::GetUseCase::new(uow_factory);
88 Ok(uc.execute_all()?.into_iter().map(|e| e.into()).collect())
89}
90
91pub fn get_multi(db_context: &DbContext, ids: &[EntityId]) -> Result<Vec<Option<ListDto>>> {
92 let uow_factory = ListReadUoWFactory::new(db_context);
93 let uc = use_cases::GetUseCase::new(uow_factory);
94 Ok(uc
95 .execute_multi(ids)?
96 .into_iter()
97 .map(|o| o.map(|e| e.into()))
98 .collect())
99}
100
101pub fn update(
102 db_context: &DbContext,
103 event_hub: &Arc<EventHub>,
104 undo_redo_manager: &mut UndoRedoManager,
105 stack_id: Option<u64>,
106 entity: &UpdateListDto,
107) -> Result<ListDto> {
108 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
109 let entity_in: common::entities::List = entity.into();
110 let mut uc = use_cases::UndoableUpdateUseCase::new(uow_factory);
111 let result = uc.execute(&entity_in)?;
112 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
113 Ok(result.into())
114}
115
116pub fn update_multi(
117 db_context: &DbContext,
118 event_hub: &Arc<EventHub>,
119 undo_redo_manager: &mut UndoRedoManager,
120 stack_id: Option<u64>,
121 entities: &[UpdateListDto],
122) -> Result<Vec<ListDto>> {
123 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
124 let entities_in: Vec<common::entities::List> = entities.iter().map(|dto| dto.into()).collect();
125 let mut uc = use_cases::UndoableUpdateUseCase::new(uow_factory);
126 let result = uc.execute_multi(&entities_in)?;
127 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
128 Ok(result.into_iter().map(|e| e.into()).collect())
129}
130
131pub fn update_with_relationships(
132 db_context: &DbContext,
133 event_hub: &Arc<EventHub>,
134 undo_redo_manager: &mut UndoRedoManager,
135 stack_id: Option<u64>,
136 entity: &ListDto,
137) -> Result<ListDto> {
138 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
139 let entity_in: common::entities::List = entity.into();
140 let mut uc = use_cases::UndoableUpdateWithRelationshipsUseCase::new(uow_factory);
141 let result = uc.execute(&entity_in)?;
142 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
143 Ok(result.into())
144}
145
146pub fn update_with_relationships_multi(
147 db_context: &DbContext,
148 event_hub: &Arc<EventHub>,
149 undo_redo_manager: &mut UndoRedoManager,
150 stack_id: Option<u64>,
151 entities: &[ListDto],
152) -> Result<Vec<ListDto>> {
153 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
154 let entities_in: Vec<common::entities::List> = entities.iter().map(|dto| dto.into()).collect();
155 let mut uc = use_cases::UndoableUpdateWithRelationshipsUseCase::new(uow_factory);
156 let result = uc.execute_multi(&entities_in)?;
157 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
158 Ok(result.into_iter().map(|e| e.into()).collect())
159}
160
161pub fn remove(
162 db_context: &DbContext,
163 event_hub: &Arc<EventHub>,
164 undo_redo_manager: &mut UndoRedoManager,
165 stack_id: Option<u64>,
166 id: &EntityId,
167) -> Result<()> {
168 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
169 let mut uc = use_cases::UndoableRemoveUseCase::new(uow_factory);
170 uc.execute(id)?;
171 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
172 Ok(())
173}
174
175pub fn remove_multi(
176 db_context: &DbContext,
177 event_hub: &Arc<EventHub>,
178 undo_redo_manager: &mut UndoRedoManager,
179 stack_id: Option<u64>,
180 ids: &[EntityId],
181) -> Result<()> {
182 let uow_factory = ListWriteUoWFactory::new(db_context, event_hub);
183 let mut uc = use_cases::UndoableRemoveUseCase::new(uow_factory);
184 uc.execute_multi(ids)?;
185 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
186 Ok(())
187}
188
189#[cfg(test)]
190mod tests {
191 #![allow(dead_code)]
192 #![allow(unused_imports)]
193
194 use super::*;
195 use crate::document::document_controller;
196 use crate::document::dtos::CreateDocumentDto;
197 use crate::root::dtos::CreateRootDto;
198 use crate::root::root_controller;
199 use common::database::db_context::DbContext;
200 use common::event::EventHub;
201 use common::types::EntityId;
202 use common::undo_redo::UndoRedoManager;
203 use std::sync::Arc;
204
205 struct TestContext {
206 db: DbContext,
207 hub: Arc<EventHub>,
208 undo: UndoRedoManager,
209 }
210
211 impl TestContext {
212 fn new() -> Self {
213 let db = DbContext::new().expect("Failed to create in-memory DB");
214 let hub = Arc::new(EventHub::new());
215 let mut undo = UndoRedoManager::new();
216 undo.set_event_hub(&hub);
217 TestContext { db, hub, undo }
218 }
219 }
220
221 fn create_owner_chain(ctx: &mut TestContext) -> EntityId {
223 let root =
224 root_controller::create_orphan(&ctx.db, &ctx.hub, &CreateRootDto::default()).unwrap();
225 let document = document_controller::create(
226 &ctx.db,
227 &ctx.hub,
228 &mut ctx.undo,
229 None,
230 &CreateDocumentDto::default(),
231 root.id,
232 -1,
233 )
234 .unwrap();
235 document.id
236 }
237
238 fn create_one(ctx: &mut TestContext) -> ListDto {
240 create_orphan(
241 &ctx.db,
242 &ctx.hub,
243 &mut ctx.undo,
244 None,
245 &CreateListDto::default(),
246 )
247 .unwrap()
248 }
249
250 #[test]
255 fn test_create_orphan_and_get() {
256 let mut ctx = TestContext::new();
257 let created = create_one(&mut ctx);
258 assert!(created.id > 0);
259
260 let fetched = get(&ctx.db, &created.id).unwrap();
261 assert!(fetched.is_some());
262 assert_eq!(fetched.unwrap().id, created.id);
263 }
264
265 #[test]
270 fn test_get_nonexistent() {
271 let ctx = TestContext::new();
272 assert!(get(&ctx.db, &999999).unwrap().is_none());
273 }
274
275 #[test]
280 fn test_get_all() {
281 let mut ctx = TestContext::new();
282 create_one(&mut ctx);
283 let all = get_all(&ctx.db).unwrap();
284 assert!(!all.is_empty());
285 }
286
287 #[test]
292 fn test_get_multi() {
293 let mut ctx = TestContext::new();
294 let a = create_one(&mut ctx);
295 let results = get_multi(&ctx.db, &[a.id, 999999]).unwrap();
296 assert_eq!(results.len(), 2);
297 assert!(results[0].is_some());
298 assert!(results[1].is_none());
299 }
300
301 #[test]
306 fn test_update() {
307 let mut ctx = TestContext::new();
308 let created = create_one(&mut ctx);
309 let update_dto: UpdateListDto = created.into();
310 let updated = update(&ctx.db, &ctx.hub, &mut ctx.undo, None, &update_dto).unwrap();
311 assert_eq!(updated.id, update_dto.id);
312 }
313
314 #[test]
319 fn test_remove() {
320 let mut ctx = TestContext::new();
321 let created = create_one(&mut ctx);
322 remove(&ctx.db, &ctx.hub, &mut ctx.undo, None, &created.id).unwrap();
323 assert!(get(&ctx.db, &created.id).unwrap().is_none());
324 }
325
326 #[test]
331 fn test_remove_multi() {
332 let mut ctx = TestContext::new();
333 let a = create_one(&mut ctx);
334 remove_multi(&ctx.db, &ctx.hub, &mut ctx.undo, None, &[a.id]).unwrap();
335 assert!(get(&ctx.db, &a.id).unwrap().is_none());
336 }
337
338 #[test]
343 fn test_create_with_owner() {
344 let mut ctx = TestContext::new();
345 let owner_id = create_owner_chain(&mut ctx);
346 let created = create(
347 &ctx.db,
348 &ctx.hub,
349 &mut ctx.undo,
350 None,
351 &CreateListDto::default(),
352 owner_id,
353 -1,
354 )
355 .unwrap();
356 assert!(created.id > 0);
357 let fetched = get(&ctx.db, &created.id).unwrap();
358 assert!(fetched.is_some());
359 }
360
361 #[test]
366 fn test_create_orphan_undo() {
367 let mut ctx = TestContext::new();
368 let created = create_one(&mut ctx);
369 assert!(get(&ctx.db, &created.id).unwrap().is_some());
370 ctx.undo.undo(None).unwrap();
371 assert!(get(&ctx.db, &created.id).unwrap().is_none());
372 }
373
374 #[test]
379 fn test_remove_undo() {
380 let mut ctx = TestContext::new();
381 let created = create_one(&mut ctx);
382 remove(&ctx.db, &ctx.hub, &mut ctx.undo, None, &created.id).unwrap();
383 assert!(get(&ctx.db, &created.id).unwrap().is_none());
384 ctx.undo.undo(None).unwrap();
385 assert!(get(&ctx.db, &created.id).unwrap().is_some());
386 }
387}