1use super::{
4 dtos::{CreateInlineElementDto, InlineElementDto, UpdateInlineElementDto},
5 units_of_work::{InlineElementReadUoWFactory, InlineElementWriteUoWFactory},
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: &CreateInlineElementDto,
19) -> Result<InlineElementDto> {
20 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
21 let mut uc = use_cases::UndoableCreateOrphanUseCase::new(uow_factory);
22 let entity_in: common::entities::InlineElement = 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: &[CreateInlineElementDto],
34) -> Result<Vec<InlineElementDto>> {
35 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
36 let entities_in: Vec<common::entities::InlineElement> =
37 entities.iter().map(|dto| dto.into()).collect();
38 let mut uc = use_cases::UndoableCreateOrphanUseCase::new(uow_factory);
39 let result = uc.execute_multi(&entities_in)?;
40 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
41 Ok(result.into_iter().map(|e| e.into()).collect())
42}
43
44pub fn create(
45 db_context: &DbContext,
46 event_hub: &Arc<EventHub>,
47 undo_redo_manager: &mut UndoRedoManager,
48 stack_id: Option<u64>,
49 entity: &CreateInlineElementDto,
50 owner_id: EntityId,
51 index: i32,
52) -> Result<InlineElementDto> {
53 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
54 let entity_in: common::entities::InlineElement = entity.into();
55 let strategy = use_cases::OwnerStrategy::Appending;
56 let mut uc = use_cases::UndoableCreateUseCase::new(uow_factory, strategy);
57 let result = uc.execute(&entity_in, owner_id, index)?;
58 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
59 Ok(result.into())
60}
61
62pub fn create_multi(
63 db_context: &DbContext,
64 event_hub: &Arc<EventHub>,
65 undo_redo_manager: &mut UndoRedoManager,
66 stack_id: Option<u64>,
67 entities: &[CreateInlineElementDto],
68 owner_id: EntityId,
69 index: i32,
70) -> Result<Vec<InlineElementDto>> {
71 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
72 let entities_in: Vec<common::entities::InlineElement> =
73 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<InlineElementDto>> {
82 let uow_factory = InlineElementReadUoWFactory::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<InlineElementDto>> {
88 let uow_factory = InlineElementReadUoWFactory::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(
94 db_context: &DbContext,
95 ids: &[EntityId],
96) -> Result<Vec<Option<InlineElementDto>>> {
97 let uow_factory = InlineElementReadUoWFactory::new(db_context);
98 let uc = use_cases::GetUseCase::new(uow_factory);
99 Ok(uc
100 .execute_multi(ids)?
101 .into_iter()
102 .map(|o| o.map(|e| e.into()))
103 .collect())
104}
105
106pub fn update(
107 db_context: &DbContext,
108 event_hub: &Arc<EventHub>,
109 undo_redo_manager: &mut UndoRedoManager,
110 stack_id: Option<u64>,
111 entity: &UpdateInlineElementDto,
112) -> Result<InlineElementDto> {
113 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
114 let entity_in: common::entities::InlineElement = entity.into();
115 let mut uc = use_cases::UndoableUpdateUseCase::new(uow_factory);
116 let result = uc.execute(&entity_in)?;
117 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
118 Ok(result.into())
119}
120
121pub fn update_multi(
122 db_context: &DbContext,
123 event_hub: &Arc<EventHub>,
124 undo_redo_manager: &mut UndoRedoManager,
125 stack_id: Option<u64>,
126 entities: &[UpdateInlineElementDto],
127) -> Result<Vec<InlineElementDto>> {
128 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
129 let entities_in: Vec<common::entities::InlineElement> =
130 entities.iter().map(|dto| dto.into()).collect();
131 let mut uc = use_cases::UndoableUpdateUseCase::new(uow_factory);
132 let result = uc.execute_multi(&entities_in)?;
133 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
134 Ok(result.into_iter().map(|e| e.into()).collect())
135}
136
137pub fn update_with_relationships(
138 db_context: &DbContext,
139 event_hub: &Arc<EventHub>,
140 undo_redo_manager: &mut UndoRedoManager,
141 stack_id: Option<u64>,
142 entity: &InlineElementDto,
143) -> Result<InlineElementDto> {
144 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
145 let entity_in: common::entities::InlineElement = entity.into();
146 let mut uc = use_cases::UndoableUpdateWithRelationshipsUseCase::new(uow_factory);
147 let result = uc.execute(&entity_in)?;
148 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
149 Ok(result.into())
150}
151
152pub fn update_with_relationships_multi(
153 db_context: &DbContext,
154 event_hub: &Arc<EventHub>,
155 undo_redo_manager: &mut UndoRedoManager,
156 stack_id: Option<u64>,
157 entities: &[InlineElementDto],
158) -> Result<Vec<InlineElementDto>> {
159 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
160 let entities_in: Vec<common::entities::InlineElement> =
161 entities.iter().map(|dto| dto.into()).collect();
162 let mut uc = use_cases::UndoableUpdateWithRelationshipsUseCase::new(uow_factory);
163 let result = uc.execute_multi(&entities_in)?;
164 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
165 Ok(result.into_iter().map(|e| e.into()).collect())
166}
167
168pub fn remove(
169 db_context: &DbContext,
170 event_hub: &Arc<EventHub>,
171 undo_redo_manager: &mut UndoRedoManager,
172 stack_id: Option<u64>,
173 id: &EntityId,
174) -> Result<()> {
175 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
176 let mut uc = use_cases::UndoableRemoveUseCase::new(uow_factory);
177 uc.execute(id)?;
178 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
179 Ok(())
180}
181
182pub fn remove_multi(
183 db_context: &DbContext,
184 event_hub: &Arc<EventHub>,
185 undo_redo_manager: &mut UndoRedoManager,
186 stack_id: Option<u64>,
187 ids: &[EntityId],
188) -> Result<()> {
189 let uow_factory = InlineElementWriteUoWFactory::new(db_context, event_hub);
190 let mut uc = use_cases::UndoableRemoveUseCase::new(uow_factory);
191 uc.execute_multi(ids)?;
192 undo_redo_manager.add_command_to_stack(Box::new(uc), stack_id)?;
193 Ok(())
194}
195
196#[cfg(test)]
197mod tests {
198 #![allow(dead_code)]
199 #![allow(unused_imports)]
200
201 use super::*;
202 use crate::block::block_controller;
203 use crate::block::dtos::CreateBlockDto;
204 use crate::document::document_controller;
205 use crate::document::dtos::CreateDocumentDto;
206 use crate::frame::dtos::CreateFrameDto;
207 use crate::frame::frame_controller;
208 use crate::root::dtos::CreateRootDto;
209 use crate::root::root_controller;
210 use common::database::db_context::DbContext;
211 use common::event::EventHub;
212 use common::types::EntityId;
213 use common::undo_redo::UndoRedoManager;
214 use std::sync::Arc;
215
216 struct TestContext {
217 db: DbContext,
218 hub: Arc<EventHub>,
219 undo: UndoRedoManager,
220 }
221
222 impl TestContext {
223 fn new() -> Self {
224 let db = DbContext::new().expect("Failed to create in-memory DB");
225 let hub = Arc::new(EventHub::new());
226 let mut undo = UndoRedoManager::new();
227 undo.set_event_hub(&hub);
228 TestContext { db, hub, undo }
229 }
230 }
231
232 fn create_owner_chain(ctx: &mut TestContext) -> EntityId {
234 let root =
235 root_controller::create_orphan(&ctx.db, &ctx.hub, &CreateRootDto::default()).unwrap();
236 let document = document_controller::create(
237 &ctx.db,
238 &ctx.hub,
239 &mut ctx.undo,
240 None,
241 &CreateDocumentDto::default(),
242 root.id,
243 -1,
244 )
245 .unwrap();
246 let frame = frame_controller::create(
247 &ctx.db,
248 &ctx.hub,
249 &mut ctx.undo,
250 None,
251 &CreateFrameDto::default(),
252 document.id,
253 -1,
254 )
255 .unwrap();
256 let block = block_controller::create(
257 &ctx.db,
258 &ctx.hub,
259 &mut ctx.undo,
260 None,
261 &CreateBlockDto::default(),
262 frame.id,
263 -1,
264 )
265 .unwrap();
266 block.id
267 }
268
269 fn create_one(ctx: &mut TestContext) -> InlineElementDto {
271 create_orphan(
272 &ctx.db,
273 &ctx.hub,
274 &mut ctx.undo,
275 None,
276 &CreateInlineElementDto::default(),
277 )
278 .unwrap()
279 }
280
281 #[test]
286 fn test_create_orphan_and_get() {
287 let mut ctx = TestContext::new();
288 let created = create_one(&mut ctx);
289 assert!(created.id > 0);
290
291 let fetched = get(&ctx.db, &created.id).unwrap();
292 assert!(fetched.is_some());
293 assert_eq!(fetched.unwrap().id, created.id);
294 }
295
296 #[test]
301 fn test_get_nonexistent() {
302 let ctx = TestContext::new();
303 assert!(get(&ctx.db, &999999).unwrap().is_none());
304 }
305
306 #[test]
311 fn test_get_all() {
312 let mut ctx = TestContext::new();
313 create_one(&mut ctx);
314 let all = get_all(&ctx.db).unwrap();
315 assert!(!all.is_empty());
316 }
317
318 #[test]
323 fn test_get_multi() {
324 let mut ctx = TestContext::new();
325 let a = create_one(&mut ctx);
326 let results = get_multi(&ctx.db, &[a.id, 999999]).unwrap();
327 assert_eq!(results.len(), 2);
328 assert!(results[0].is_some());
329 assert!(results[1].is_none());
330 }
331
332 #[test]
337 fn test_update() {
338 let mut ctx = TestContext::new();
339 let created = create_one(&mut ctx);
340 let update_dto: UpdateInlineElementDto = created.into();
341 let updated = update(&ctx.db, &ctx.hub, &mut ctx.undo, None, &update_dto).unwrap();
342 assert_eq!(updated.id, update_dto.id);
343 }
344
345 #[test]
350 fn test_remove() {
351 let mut ctx = TestContext::new();
352 let created = create_one(&mut ctx);
353 remove(&ctx.db, &ctx.hub, &mut ctx.undo, None, &created.id).unwrap();
354 assert!(get(&ctx.db, &created.id).unwrap().is_none());
355 }
356
357 #[test]
362 fn test_remove_multi() {
363 let mut ctx = TestContext::new();
364 let a = create_one(&mut ctx);
365 remove_multi(&ctx.db, &ctx.hub, &mut ctx.undo, None, &[a.id]).unwrap();
366 assert!(get(&ctx.db, &a.id).unwrap().is_none());
367 }
368
369 #[test]
374 fn test_create_with_owner() {
375 let mut ctx = TestContext::new();
376 let owner_id = create_owner_chain(&mut ctx);
377 let created = create(
378 &ctx.db,
379 &ctx.hub,
380 &mut ctx.undo,
381 None,
382 &CreateInlineElementDto::default(),
383 owner_id,
384 -1,
385 )
386 .unwrap();
387 assert!(created.id > 0);
388 let fetched = get(&ctx.db, &created.id).unwrap();
389 assert!(fetched.is_some());
390 }
391
392 #[test]
397 fn test_create_orphan_undo() {
398 let mut ctx = TestContext::new();
399 let created = create_one(&mut ctx);
400 assert!(get(&ctx.db, &created.id).unwrap().is_some());
401 ctx.undo.undo(None).unwrap();
402 assert!(get(&ctx.db, &created.id).unwrap().is_none());
403 }
404
405 #[test]
410 fn test_remove_undo() {
411 let mut ctx = TestContext::new();
412 let created = create_one(&mut ctx);
413 remove(&ctx.db, &ctx.hub, &mut ctx.undo, None, &created.id).unwrap();
414 assert!(get(&ctx.db, &created.id).unwrap().is_none());
415 ctx.undo.undo(None).unwrap();
416 assert!(get(&ctx.db, &created.id).unwrap().is_some());
417 }
418}