1use super::{
4 dtos::{CreateFrameDto, FrameDto, UpdateFrameDto},
5 units_of_work::{FrameReadUoWFactory, FrameWriteUoWFactory},
6};
7use crate::FrameRelationshipDto;
8use anyhow::{Ok, Result};
9use common::direct_access::frame::FrameRelationshipField;
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: &CreateFrameDto,
21) -> Result<FrameDto> {
22 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
23 let mut uc = use_cases::UndoableCreateOrphanUseCase::new(uow_factory);
24 let entity_in: common::entities::Frame = 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: &[CreateFrameDto],
36) -> Result<Vec<FrameDto>> {
37 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
38 let entities_in: Vec<common::entities::Frame> = 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: &CreateFrameDto,
51 owner_id: EntityId,
52 index: i32,
53) -> Result<FrameDto> {
54 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
55 let entity_in: common::entities::Frame = 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: &[CreateFrameDto],
69 owner_id: EntityId,
70 index: i32,
71) -> Result<Vec<FrameDto>> {
72 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
73 let entities_in: Vec<common::entities::Frame> = 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<FrameDto>> {
82 let uow_factory = FrameReadUoWFactory::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<FrameDto>> {
88 let uow_factory = FrameReadUoWFactory::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<FrameDto>>> {
94 let uow_factory = FrameReadUoWFactory::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: &UpdateFrameDto,
109) -> Result<FrameDto> {
110 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
111 let entity_in: common::entities::Frame = 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: &[UpdateFrameDto],
124) -> Result<Vec<FrameDto>> {
125 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
126 let entities_in: Vec<common::entities::Frame> = 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: &FrameDto,
139) -> Result<FrameDto> {
140 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
141 let entity_in: common::entities::Frame = 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: &[FrameDto],
154) -> Result<Vec<FrameDto>> {
155 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
156 let entities_in: Vec<common::entities::Frame> = 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 = FrameWriteUoWFactory::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 = FrameWriteUoWFactory::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: &FrameRelationshipField,
195) -> Result<Vec<EntityId>> {
196 let uow_factory = FrameReadUoWFactory::new(db_context);
197 let uc = use_cases::GetRelationshipUseCase::<FrameRelationshipField, _>::new(uow_factory);
198 uc.execute(id, field)
199}
200
201pub fn get_relationship_many(
202 db_context: &DbContext,
203 ids: &[EntityId],
204 field: &FrameRelationshipField,
205) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>> {
206 let uow_factory = FrameReadUoWFactory::new(db_context);
207 let uc = use_cases::GetRelationshipManyUseCase::<FrameRelationshipField, _>::new(uow_factory);
208 uc.execute(ids, field)
209}
210
211pub fn get_relationship_count(
212 db_context: &DbContext,
213 id: &EntityId,
214 field: &FrameRelationshipField,
215) -> Result<usize> {
216 let uow_factory = FrameReadUoWFactory::new(db_context);
217 let uc = use_cases::GetRelationshipCountUseCase::<FrameRelationshipField, _>::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: &FrameRelationshipField,
225 offset: usize,
226 limit: usize,
227) -> Result<Vec<EntityId>> {
228 let uow_factory = FrameReadUoWFactory::new(db_context);
229 let uc =
230 use_cases::GetRelationshipInRangeUseCase::<FrameRelationshipField, _>::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: &FrameRelationshipDto,
240) -> Result<()> {
241 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
242 let mut uc =
243 use_cases::UndoableSetRelationshipUseCase::<FrameRelationshipField, _>::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: &FrameRelationshipField,
256 ids_to_move: &[EntityId],
257 new_index: i32,
258) -> Result<Vec<EntityId>> {
259 let uow_factory = FrameWriteUoWFactory::new(db_context, event_hub);
260 let mut uc =
261 use_cases::UndoableMoveRelationshipUseCase::<FrameRelationshipField, _>::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::root::dtos::CreateRootDto;
276 use crate::root::root_controller;
277 use common::database::db_context::DbContext;
278 use common::event::EventHub;
279 use common::types::EntityId;
280 use common::undo_redo::UndoRedoManager;
281 use std::sync::Arc;
282
283 struct TestContext {
284 db: DbContext,
285 hub: Arc<EventHub>,
286 undo: UndoRedoManager,
287 }
288
289 impl TestContext {
290 fn new() -> Self {
291 let db = DbContext::new().expect("Failed to create in-memory DB");
292 let hub = Arc::new(EventHub::new());
293 let mut undo = UndoRedoManager::new();
294 undo.set_event_hub(&hub);
295 TestContext { db, hub, undo }
296 }
297 }
298
299 fn create_owner_chain(ctx: &mut TestContext) -> EntityId {
301 let root =
302 root_controller::create_orphan(&ctx.db, &ctx.hub, &CreateRootDto::default()).unwrap();
303 let document = document_controller::create(
304 &ctx.db,
305 &ctx.hub,
306 &mut ctx.undo,
307 None,
308 &CreateDocumentDto::default(),
309 root.id,
310 -1,
311 )
312 .unwrap();
313 document.id
314 }
315
316 fn create_one(ctx: &mut TestContext) -> FrameDto {
318 create_orphan(
319 &ctx.db,
320 &ctx.hub,
321 &mut ctx.undo,
322 None,
323 &CreateFrameDto::default(),
324 )
325 .unwrap()
326 }
327
328 #[test]
333 fn test_create_orphan_and_get() {
334 let mut ctx = TestContext::new();
335 let created = create_one(&mut ctx);
336 assert!(created.id > 0);
337
338 let fetched = get(&ctx.db, &created.id).unwrap();
339 assert!(fetched.is_some());
340 assert_eq!(fetched.unwrap().id, created.id);
341 }
342
343 #[test]
348 fn test_get_nonexistent() {
349 let ctx = TestContext::new();
350 assert!(get(&ctx.db, &999999).unwrap().is_none());
351 }
352
353 #[test]
358 fn test_get_all() {
359 let mut ctx = TestContext::new();
360 create_one(&mut ctx);
361 let all = get_all(&ctx.db).unwrap();
362 assert!(!all.is_empty());
363 }
364
365 #[test]
370 fn test_get_multi() {
371 let mut ctx = TestContext::new();
372 let a = create_one(&mut ctx);
373 let results = get_multi(&ctx.db, &[a.id, 999999]).unwrap();
374 assert_eq!(results.len(), 2);
375 assert!(results[0].is_some());
376 assert!(results[1].is_none());
377 }
378
379 #[test]
384 fn test_update() {
385 let mut ctx = TestContext::new();
386 let created = create_one(&mut ctx);
387 let update_dto: UpdateFrameDto = created.into();
388 let updated = update(&ctx.db, &ctx.hub, &mut ctx.undo, None, &update_dto).unwrap();
389 assert_eq!(updated.id, update_dto.id);
390 }
391
392 #[test]
397 fn test_remove() {
398 let mut ctx = TestContext::new();
399 let created = create_one(&mut ctx);
400 remove(&ctx.db, &ctx.hub, &mut ctx.undo, None, &created.id).unwrap();
401 assert!(get(&ctx.db, &created.id).unwrap().is_none());
402 }
403
404 #[test]
409 fn test_remove_multi() {
410 let mut ctx = TestContext::new();
411 let a = create_one(&mut ctx);
412 remove_multi(&ctx.db, &ctx.hub, &mut ctx.undo, None, &[a.id]).unwrap();
413 assert!(get(&ctx.db, &a.id).unwrap().is_none());
414 }
415
416 #[test]
421 fn test_create_with_owner() {
422 let mut ctx = TestContext::new();
423 let owner_id = create_owner_chain(&mut ctx);
424 let created = create(
425 &ctx.db,
426 &ctx.hub,
427 &mut ctx.undo,
428 None,
429 &CreateFrameDto::default(),
430 owner_id,
431 -1,
432 )
433 .unwrap();
434 assert!(created.id > 0);
435 let fetched = get(&ctx.db, &created.id).unwrap();
436 assert!(fetched.is_some());
437 }
438
439 #[test]
444 fn test_create_orphan_undo() {
445 let mut ctx = TestContext::new();
446 let created = create_one(&mut ctx);
447 assert!(get(&ctx.db, &created.id).unwrap().is_some());
448 ctx.undo.undo(None).unwrap();
449 assert!(get(&ctx.db, &created.id).unwrap().is_none());
450 }
451
452 #[test]
457 fn test_remove_undo() {
458 let mut ctx = TestContext::new();
459 let created = create_one(&mut ctx);
460 remove(&ctx.db, &ctx.hub, &mut ctx.undo, None, &created.id).unwrap();
461 assert!(get(&ctx.db, &created.id).unwrap().is_none());
462 ctx.undo.undo(None).unwrap();
463 assert!(get(&ctx.db, &created.id).unwrap().is_some());
464 }
465
466 #[test]
471 fn test_get_relationship_empty() {
472 let mut ctx = TestContext::new();
473 let created = create_one(&mut ctx);
474 let rel_ids =
475 get_relationship(&ctx.db, &created.id, &FrameRelationshipField::Blocks).unwrap();
476 assert!(rel_ids.is_empty());
477 }
478
479 #[test]
484 fn test_get_relationship_count_zero() {
485 let mut ctx = TestContext::new();
486 let created = create_one(&mut ctx);
487 let count =
488 get_relationship_count(&ctx.db, &created.id, &FrameRelationshipField::Blocks).unwrap();
489 assert_eq!(count, 0);
490 }
491}