1use super::{
4 dtos::{BlockDto, CreateBlockDto, UpdateBlockDto},
5 units_of_work::{BlockReadUoWFactory, BlockWriteUoWFactory},
6};
7use crate::BlockRelationshipDto;
8use anyhow::{Ok, Result};
9use common::direct_access::block::BlockRelationshipField;
10use common::direct_access::use_cases;
11use common::undo_redo::UndoRedoManager;
12use common::{database::db_context::DbContext, event::EventHub, types::EntityId};
13use std::sync::Arc;
14
15pub fn create_orphan(
16 db_context: &DbContext,
17 event_hub: &Arc<EventHub>,
18 undo_redo_manager: &mut UndoRedoManager,
19 stack_id: Option<u64>,
20 entity: &CreateBlockDto,
21) -> Result<BlockDto> {
22 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
23 let mut uc = use_cases::UndoableCreateOrphanUseCase::new(uow_factory);
24 let entity_in: common::entities::Block = entity.into();
25 let result = uc.execute(&entity_in)?;
26 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
27 Ok(result.into())
28}
29
30pub fn create_orphan_multi(
31 db_context: &DbContext,
32 event_hub: &Arc<EventHub>,
33 undo_redo_manager: &mut UndoRedoManager,
34 stack_id: Option<u64>,
35 entities: &[CreateBlockDto],
36) -> Result<Vec<BlockDto>> {
37 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
38 let entities_in: Vec<common::entities::Block> = entities.iter().map(|dto| dto.into()).collect();
39 let mut uc = use_cases::UndoableCreateOrphanUseCase::new(uow_factory);
40 let result = uc.execute_multi(&entities_in)?;
41 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
42 Ok(result.into_iter().map(|e| e.into()).collect())
43}
44
45pub fn create(
46 db_context: &DbContext,
47 event_hub: &Arc<EventHub>,
48 undo_redo_manager: &mut UndoRedoManager,
49 stack_id: Option<u64>,
50 entity: &CreateBlockDto,
51 owner_id: EntityId,
52 index: i32,
53) -> Result<BlockDto> {
54 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
55 let entity_in: common::entities::Block = entity.into();
56 let strategy = use_cases::OwnerStrategy::Appending;
57 let mut uc = use_cases::UndoableCreateUseCase::new(uow_factory, strategy);
58 let result = uc.execute(&entity_in, owner_id, index)?;
59 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
60 Ok(result.into())
61}
62
63pub fn create_multi(
64 db_context: &DbContext,
65 event_hub: &Arc<EventHub>,
66 undo_redo_manager: &mut UndoRedoManager,
67 stack_id: Option<u64>,
68 entities: &[CreateBlockDto],
69 owner_id: EntityId,
70 index: i32,
71) -> Result<Vec<BlockDto>> {
72 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
73 let entities_in: Vec<common::entities::Block> = entities.iter().map(|dto| dto.into()).collect();
74 let strategy = use_cases::OwnerStrategy::Appending;
75 let mut uc = use_cases::UndoableCreateUseCase::new(uow_factory, strategy);
76 let result = uc.execute_multi(&entities_in, owner_id, index)?;
77 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
78 Ok(result.into_iter().map(|e| e.into()).collect())
79}
80
81pub fn get(db_context: &DbContext, id: &EntityId) -> Result<Option<BlockDto>> {
82 let uow_factory = BlockReadUoWFactory::new(db_context);
83 let uc = use_cases::GetUseCase::new(uow_factory);
84 Ok(uc.execute(id)?.map(|e| e.into()))
85}
86
87pub fn get_all(db_context: &DbContext) -> Result<Vec<BlockDto>> {
88 let uow_factory = BlockReadUoWFactory::new(db_context);
89 let uc = use_cases::GetUseCase::new(uow_factory);
90 Ok(uc.execute_all()?.into_iter().map(|e| e.into()).collect())
91}
92
93pub fn get_multi(db_context: &DbContext, ids: &[EntityId]) -> Result<Vec<Option<BlockDto>>> {
94 let uow_factory = BlockReadUoWFactory::new(db_context);
95 let uc = use_cases::GetUseCase::new(uow_factory);
96 Ok(uc
97 .execute_multi(ids)?
98 .into_iter()
99 .map(|o| o.map(|e| e.into()))
100 .collect())
101}
102
103pub fn update(
104 db_context: &DbContext,
105 event_hub: &Arc<EventHub>,
106 undo_redo_manager: &mut UndoRedoManager,
107 stack_id: Option<u64>,
108 entity: &UpdateBlockDto,
109) -> Result<BlockDto> {
110 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
111 let entity_in: common::entities::Block = entity.into();
112 let mut uc = use_cases::UndoableUpdateUseCase::new(uow_factory);
113 let result = uc.execute(&entity_in)?;
114 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
115 Ok(result.into())
116}
117
118pub fn update_multi(
119 db_context: &DbContext,
120 event_hub: &Arc<EventHub>,
121 undo_redo_manager: &mut UndoRedoManager,
122 stack_id: Option<u64>,
123 entities: &[UpdateBlockDto],
124) -> Result<Vec<BlockDto>> {
125 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
126 let entities_in: Vec<common::entities::Block> = entities.iter().map(|dto| dto.into()).collect();
127 let mut uc = use_cases::UndoableUpdateUseCase::new(uow_factory);
128 let result = uc.execute_multi(&entities_in)?;
129 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
130 Ok(result.into_iter().map(|e| e.into()).collect())
131}
132
133pub fn update_with_relationships(
134 db_context: &DbContext,
135 event_hub: &Arc<EventHub>,
136 undo_redo_manager: &mut UndoRedoManager,
137 stack_id: Option<u64>,
138 entity: &BlockDto,
139) -> Result<BlockDto> {
140 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
141 let entity_in: common::entities::Block = entity.into();
142 let mut uc = use_cases::UndoableUpdateWithRelationshipsUseCase::new(uow_factory);
143 let result = uc.execute(&entity_in)?;
144 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
145 Ok(result.into())
146}
147
148pub fn update_with_relationships_multi(
149 db_context: &DbContext,
150 event_hub: &Arc<EventHub>,
151 undo_redo_manager: &mut UndoRedoManager,
152 stack_id: Option<u64>,
153 entities: &[BlockDto],
154) -> Result<Vec<BlockDto>> {
155 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
156 let entities_in: Vec<common::entities::Block> = entities.iter().map(|dto| dto.into()).collect();
157 let mut uc = use_cases::UndoableUpdateWithRelationshipsUseCase::new(uow_factory);
158 let result = uc.execute_multi(&entities_in)?;
159 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
160 Ok(result.into_iter().map(|e| e.into()).collect())
161}
162
163pub fn remove(
164 db_context: &DbContext,
165 event_hub: &Arc<EventHub>,
166 undo_redo_manager: &mut UndoRedoManager,
167 stack_id: Option<u64>,
168 id: &EntityId,
169) -> Result<()> {
170 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
171 let mut uc = use_cases::UndoableRemoveUseCase::new(uow_factory);
172 uc.execute(id)?;
173 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
174 Ok(())
175}
176
177pub fn remove_multi(
178 db_context: &DbContext,
179 event_hub: &Arc<EventHub>,
180 undo_redo_manager: &mut UndoRedoManager,
181 stack_id: Option<u64>,
182 ids: &[EntityId],
183) -> Result<()> {
184 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
185 let mut uc = use_cases::UndoableRemoveUseCase::new(uow_factory);
186 uc.execute_multi(ids)?;
187 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
188 Ok(())
189}
190
191pub fn get_relationship(
192 db_context: &DbContext,
193 id: &EntityId,
194 field: &BlockRelationshipField,
195) -> Result<Vec<EntityId>> {
196 let uow_factory = BlockReadUoWFactory::new(db_context);
197 let uc = use_cases::GetRelationshipUseCase::<BlockRelationshipField, _>::new(uow_factory);
198 uc.execute(id, field)
199}
200
201pub fn get_relationship_many(
202 db_context: &DbContext,
203 ids: &[EntityId],
204 field: &BlockRelationshipField,
205) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>> {
206 let uow_factory = BlockReadUoWFactory::new(db_context);
207 let uc = use_cases::GetRelationshipManyUseCase::<BlockRelationshipField, _>::new(uow_factory);
208 uc.execute(ids, field)
209}
210
211pub fn get_relationship_count(
212 db_context: &DbContext,
213 id: &EntityId,
214 field: &BlockRelationshipField,
215) -> Result<usize> {
216 let uow_factory = BlockReadUoWFactory::new(db_context);
217 let uc = use_cases::GetRelationshipCountUseCase::<BlockRelationshipField, _>::new(uow_factory);
218 uc.execute(id, field)
219}
220
221pub fn get_relationship_in_range(
222 db_context: &DbContext,
223 id: &EntityId,
224 field: &BlockRelationshipField,
225 offset: usize,
226 limit: usize,
227) -> Result<Vec<EntityId>> {
228 let uow_factory = BlockReadUoWFactory::new(db_context);
229 let uc =
230 use_cases::GetRelationshipInRangeUseCase::<BlockRelationshipField, _>::new(uow_factory);
231 uc.execute(id, field, offset, limit)
232}
233
234pub fn set_relationship(
235 db_context: &DbContext,
236 event_hub: &Arc<EventHub>,
237 undo_redo_manager: &mut UndoRedoManager,
238 stack_id: Option<u64>,
239 dto: &BlockRelationshipDto,
240) -> Result<()> {
241 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
242 let mut uc =
243 use_cases::UndoableSetRelationshipUseCase::<BlockRelationshipField, _>::new(uow_factory);
244 uc.execute(&dto.id, &dto.field, dto.right_ids.as_slice())?;
245 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
246 Ok(())
247}
248
249pub fn move_relationship(
250 db_context: &DbContext,
251 event_hub: &Arc<EventHub>,
252 undo_redo_manager: &mut UndoRedoManager,
253 stack_id: Option<u64>,
254 id: &EntityId,
255 field: &BlockRelationshipField,
256 ids_to_move: &[EntityId],
257 new_index: i32,
258) -> Result<Vec<EntityId>> {
259 let uow_factory = BlockWriteUoWFactory::new(db_context, event_hub);
260 let mut uc =
261 use_cases::UndoableMoveRelationshipUseCase::<BlockRelationshipField, _>::new(uow_factory);
262 let result = uc.execute(id, field, ids_to_move, new_index)?;
263 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
264 Ok(result)
265}
266
267#[cfg(test)]
268mod tests {
269 #![allow(dead_code)]
270 #![allow(unused_imports)]
271
272 use super::*;
273 use crate::document::document_controller;
274 use crate::document::dtos::CreateDocumentDto;
275 use crate::frame::dtos::CreateFrameDto;
276 use crate::frame::frame_controller;
277 use crate::root::dtos::CreateRootDto;
278 use crate::root::root_controller;
279 use common::database::db_context::DbContext;
280 use common::event::EventHub;
281 use common::types::EntityId;
282 use common::undo_redo::UndoRedoManager;
283 use std::sync::Arc;
284
285 struct TestContext {
286 db: DbContext,
287 hub: Arc<EventHub>,
288 undo: UndoRedoManager,
289 }
290
291 impl TestContext {
292 fn new() -> Self {
293 let db = DbContext::new().expect("Failed to create in-memory DB");
294 let hub = Arc::new(EventHub::new());
295 let mut undo = UndoRedoManager::new();
296 undo.set_event_hub(&hub);
297 TestContext { db, hub, undo }
298 }
299 }
300
301 fn create_owner_chain(ctx: &mut TestContext) -> EntityId {
303 let root =
304 root_controller::create_orphan(&ctx.db, &ctx.hub, &CreateRootDto::default()).unwrap();
305 let document = document_controller::create(
306 &ctx.db,
307 &ctx.hub,
308 &mut ctx.undo,
309 None,
310 &CreateDocumentDto::default(),
311 root.id,
312 -1,
313 )
314 .unwrap();
315 let frame = frame_controller::create(
316 &ctx.db,
317 &ctx.hub,
318 &mut ctx.undo,
319 None,
320 &CreateFrameDto::default(),
321 document.id,
322 -1,
323 )
324 .unwrap();
325 frame.id
326 }
327
328 fn create_one(ctx: &mut TestContext) -> BlockDto {
330 create_orphan(
331 &ctx.db,
332 &ctx.hub,
333 &mut ctx.undo,
334 None,
335 &CreateBlockDto::default(),
336 )
337 .unwrap()
338 }
339
340 #[test]
345 fn test_create_orphan_and_get() {
346 let mut ctx = TestContext::new();
347 let created = create_one(&mut ctx);
348 assert!(created.id > 0);
349
350 let fetched = get(&ctx.db, &created.id).unwrap();
351 assert!(fetched.is_some());
352 assert_eq!(fetched.unwrap().id, created.id);
353 }
354
355 #[test]
360 fn test_get_nonexistent() {
361 let ctx = TestContext::new();
362 assert!(get(&ctx.db, &999999).unwrap().is_none());
363 }
364
365 #[test]
370 fn test_get_all() {
371 let mut ctx = TestContext::new();
372 create_one(&mut ctx);
373 let all = get_all(&ctx.db).unwrap();
374 assert!(!all.is_empty());
375 }
376
377 #[test]
382 fn test_get_multi() {
383 let mut ctx = TestContext::new();
384 let a = create_one(&mut ctx);
385 let results = get_multi(&ctx.db, &[a.id, 999999]).unwrap();
386 assert_eq!(results.len(), 2);
387 assert!(results[0].is_some());
388 assert!(results[1].is_none());
389 }
390
391 #[test]
396 fn test_update() {
397 let mut ctx = TestContext::new();
398 let created = create_one(&mut ctx);
399 let update_dto: UpdateBlockDto = created.into();
400 let updated = update(&ctx.db, &ctx.hub, &mut ctx.undo, None, &update_dto).unwrap();
401 assert_eq!(updated.id, update_dto.id);
402 }
403
404 #[test]
409 fn test_remove() {
410 let mut ctx = TestContext::new();
411 let created = create_one(&mut ctx);
412 remove(&ctx.db, &ctx.hub, &mut ctx.undo, None, &created.id).unwrap();
413 assert!(get(&ctx.db, &created.id).unwrap().is_none());
414 }
415
416 #[test]
421 fn test_remove_multi() {
422 let mut ctx = TestContext::new();
423 let a = create_one(&mut ctx);
424 remove_multi(&ctx.db, &ctx.hub, &mut ctx.undo, None, &[a.id]).unwrap();
425 assert!(get(&ctx.db, &a.id).unwrap().is_none());
426 }
427
428 #[test]
433 fn test_create_with_owner() {
434 let mut ctx = TestContext::new();
435 let owner_id = create_owner_chain(&mut ctx);
436 let created = create(
437 &ctx.db,
438 &ctx.hub,
439 &mut ctx.undo,
440 None,
441 &CreateBlockDto::default(),
442 owner_id,
443 -1,
444 )
445 .unwrap();
446 assert!(created.id > 0);
447 let fetched = get(&ctx.db, &created.id).unwrap();
448 assert!(fetched.is_some());
449 }
450
451 #[test]
456 fn test_create_orphan_undo() {
457 let mut ctx = TestContext::new();
458 let created = create_one(&mut ctx);
459 assert!(get(&ctx.db, &created.id).unwrap().is_some());
460 ctx.undo.undo(None).unwrap();
461 assert!(get(&ctx.db, &created.id).unwrap().is_none());
462 }
463
464 #[test]
469 fn test_remove_undo() {
470 let mut ctx = TestContext::new();
471 let created = create_one(&mut ctx);
472 remove(&ctx.db, &ctx.hub, &mut ctx.undo, None, &created.id).unwrap();
473 assert!(get(&ctx.db, &created.id).unwrap().is_none());
474 ctx.undo.undo(None).unwrap();
475 assert!(get(&ctx.db, &created.id).unwrap().is_some());
476 }
477
478 #[test]
483 fn test_get_relationship_empty() {
484 let mut ctx = TestContext::new();
485 let created = create_one(&mut ctx);
486 let rel_ids =
487 get_relationship(&ctx.db, &created.id, &BlockRelationshipField::Elements).unwrap();
488 assert!(rel_ids.is_empty());
489 }
490
491 #[test]
496 fn test_get_relationship_count_zero() {
497 let mut ctx = TestContext::new();
498 let created = create_one(&mut ctx);
499 let count = get_relationship_count(&ctx.db, &created.id, &BlockRelationshipField::Elements)
500 .unwrap();
501 assert_eq!(count, 0);
502 }
503}