1use std::fmt::Display;
4
5use crate::{
6 database::transactions::Transaction,
7 direct_access::repository_factory,
8 entities::Block,
9 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10 snapshot::EntityTreeSnapshot,
11 types::EntityId,
12};
13
14use crate::direct_access::frame::FrameRelationshipField;
15use crate::error::RepositoryError;
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum BlockRelationshipField {
20 List,
21}
22
23impl Display for BlockRelationshipField {
24 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
25 write!(f, "{:?}", self)
26 }
27}
28
29pub trait BlockTable {
30 fn create(&mut self, entity: &Block) -> Result<Block, RepositoryError>;
31 fn create_multi(&mut self, entities: &[Block]) -> Result<Vec<Block>, RepositoryError>;
32 fn get(&self, id: &EntityId) -> Result<Option<Block>, RepositoryError>;
33 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Block>>, RepositoryError>;
34 fn get_all(&self) -> Result<Vec<Block>, RepositoryError>;
35 fn update(&mut self, entity: &Block) -> Result<Block, RepositoryError>;
36 fn update_multi(&mut self, entities: &[Block]) -> Result<Vec<Block>, RepositoryError>;
37 fn update_with_relationships(&mut self, entity: &Block) -> Result<Block, RepositoryError>;
38 fn update_with_relationships_multi(
39 &mut self,
40 entities: &[Block],
41 ) -> Result<Vec<Block>, RepositoryError>;
42 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
43 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
44 fn get_relationship(
45 &self,
46 id: &EntityId,
47 field: &BlockRelationshipField,
48 ) -> Result<Vec<EntityId>, RepositoryError>;
49 fn get_relationship_many(
50 &self,
51 ids: &[EntityId],
52 field: &BlockRelationshipField,
53 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
54 fn get_relationship_count(
55 &self,
56 id: &EntityId,
57 field: &BlockRelationshipField,
58 ) -> Result<usize, RepositoryError>;
59 fn get_relationship_in_range(
60 &self,
61 id: &EntityId,
62 field: &BlockRelationshipField,
63 offset: usize,
64 limit: usize,
65 ) -> Result<Vec<EntityId>, RepositoryError>;
66 fn get_relationships_from_right_ids(
67 &self,
68 field: &BlockRelationshipField,
69 right_ids: &[EntityId],
70 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
71 fn set_relationship_multi(
72 &mut self,
73 field: &BlockRelationshipField,
74 relationships: Vec<(EntityId, Vec<EntityId>)>,
75 ) -> Result<(), RepositoryError>;
76 fn set_relationship(
77 &mut self,
78 id: &EntityId,
79 field: &BlockRelationshipField,
80 right_ids: &[EntityId],
81 ) -> Result<(), RepositoryError>;
82 fn move_relationship_ids(
83 &mut self,
84 id: &EntityId,
85 field: &BlockRelationshipField,
86 ids_to_move: &[EntityId],
87 new_index: i32,
88 ) -> Result<Vec<EntityId>, RepositoryError>;
89}
90
91pub trait BlockTableRO {
92 fn get(&self, id: &EntityId) -> Result<Option<Block>, RepositoryError>;
93 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Block>>, RepositoryError>;
94 fn get_all(&self) -> Result<Vec<Block>, RepositoryError>;
95 fn get_relationship(
96 &self,
97 id: &EntityId,
98 field: &BlockRelationshipField,
99 ) -> Result<Vec<EntityId>, RepositoryError>;
100 fn get_relationship_many(
101 &self,
102 ids: &[EntityId],
103 field: &BlockRelationshipField,
104 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
105 fn get_relationship_count(
106 &self,
107 id: &EntityId,
108 field: &BlockRelationshipField,
109 ) -> Result<usize, RepositoryError>;
110 fn get_relationship_in_range(
111 &self,
112 id: &EntityId,
113 field: &BlockRelationshipField,
114 offset: usize,
115 limit: usize,
116 ) -> Result<Vec<EntityId>, RepositoryError>;
117 fn get_relationships_from_right_ids(
118 &self,
119 field: &BlockRelationshipField,
120 right_ids: &[EntityId],
121 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
122}
123
124pub struct BlockRepository<'a> {
125 table: Box<dyn BlockTable + 'a>,
126 transaction: &'a Transaction,
127}
128
129impl<'a> BlockRepository<'a> {
130 pub fn new(table: Box<dyn BlockTable + 'a>, transaction: &'a Transaction) -> Self {
131 BlockRepository { table, transaction }
132 }
133
134 pub fn create_orphan(
135 &mut self,
136 event_buffer: &mut EventBuffer,
137 entity: &Block,
138 ) -> Result<Block, RepositoryError> {
139 let new = self.table.create(entity)?;
140 event_buffer.push(Event {
141 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Created)),
142 ids: vec![new.id],
143 data: None,
144 });
145 Ok(new)
146 }
147
148 pub fn create_orphan_multi(
149 &mut self,
150 event_buffer: &mut EventBuffer,
151 entities: &[Block],
152 ) -> Result<Vec<Block>, RepositoryError> {
153 let new_entities = self.table.create_multi(entities)?;
154 event_buffer.push(Event {
155 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Created)),
156 ids: new_entities.iter().map(|e| e.id).collect(),
157 data: None,
158 });
159 Ok(new_entities)
160 }
161 pub fn create(
162 &mut self,
163 event_buffer: &mut EventBuffer,
164 entity: &Block,
165 owner_id: EntityId,
166 index: i32,
167 ) -> Result<Block, RepositoryError> {
168 let new = self.table.create(entity)?;
169 let created_id = new.id;
170
171 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
172 if index >= 0 && (index as usize) < relationship_ids.len() {
174 relationship_ids.insert(index as usize, created_id);
175 } else {
176 relationship_ids.push(created_id);
177 }
178
179 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
180 event_buffer.push(Event {
181 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Created)),
182 ids: vec![created_id],
183 data: None,
184 });
185 Ok(new)
186 }
187
188 pub fn create_multi(
189 &mut self,
190 event_buffer: &mut EventBuffer,
191 entities: &[Block],
192 owner_id: EntityId,
193 index: i32,
194 ) -> Result<Vec<Block>, RepositoryError> {
195 let new_entities = self.table.create_multi(entities)?;
196 let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
197
198 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
199 if index >= 0 && (index as usize) < relationship_ids.len() {
200 for (i, id) in created_ids.iter().enumerate() {
201 relationship_ids.insert(index as usize + i, *id);
202 }
203 } else {
204 relationship_ids.extend(created_ids.iter());
205 }
206
207 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
208 event_buffer.push(Event {
209 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Created)),
210 ids: created_ids,
211 data: None,
212 });
213 Ok(new_entities)
214 }
215
216 pub fn get(&self, id: &EntityId) -> Result<Option<Block>, RepositoryError> {
217 self.table.get(id)
218 }
219 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Block>>, RepositoryError> {
220 self.table.get_multi(ids)
221 }
222 pub fn get_all(&self) -> Result<Vec<Block>, RepositoryError> {
223 self.table.get_all()
224 }
225
226 pub fn update(
227 &mut self,
228 event_buffer: &mut EventBuffer,
229 entity: &Block,
230 ) -> Result<Block, RepositoryError> {
231 let updated = self.table.update(entity)?;
232 event_buffer.push(Event {
233 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Updated)),
234 ids: vec![updated.id],
235 data: None,
236 });
237 Ok(updated)
238 }
239
240 pub fn update_multi(
241 &mut self,
242 event_buffer: &mut EventBuffer,
243 entities: &[Block],
244 ) -> Result<Vec<Block>, RepositoryError> {
245 let updated = self.table.update_multi(entities)?;
246 event_buffer.push(Event {
247 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Updated)),
248 ids: updated.iter().map(|e| e.id).collect(),
249 data: None,
250 });
251 Ok(updated)
252 }
253
254 pub fn update_with_relationships(
255 &mut self,
256 event_buffer: &mut EventBuffer,
257 entity: &Block,
258 ) -> Result<Block, RepositoryError> {
259 let updated = self.table.update_with_relationships(entity)?;
260 event_buffer.push(Event {
261 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Updated)),
262 ids: vec![updated.id],
263 data: None,
264 });
265 Ok(updated)
266 }
267
268 pub fn update_with_relationships_multi(
269 &mut self,
270 event_buffer: &mut EventBuffer,
271 entities: &[Block],
272 ) -> Result<Vec<Block>, RepositoryError> {
273 let updated = self.table.update_with_relationships_multi(entities)?;
274 event_buffer.push(Event {
275 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Updated)),
276 ids: updated.iter().map(|e| e.id).collect(),
277 data: None,
278 });
279 Ok(updated)
280 }
281
282 pub fn remove(
283 &mut self,
284 event_buffer: &mut EventBuffer,
285 id: &EntityId,
286 ) -> Result<(), RepositoryError> {
287 let _entity = match self.table.get(id)? {
288 Some(e) => e,
289 None => return Ok(()),
290 };
291 let affected_owner_ids: Vec<EntityId> = {
293 let owner_repo = repository_factory::write::create_frame_repository(self.transaction)?;
294 owner_repo
295 .get_relationships_from_right_ids(&FrameRelationshipField::Blocks, &[*id])?
296 .into_iter()
297 .map(|(owner_id, _)| owner_id)
298 .collect()
299 };
300 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
302 std::collections::HashMap::new();
303 for owner_id in &affected_owner_ids {
304 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
305 }
306
307 self.table.remove(id)?;
309 event_buffer.push(Event {
310 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Removed)),
311 ids: vec![*id],
312 data: None,
313 });
314 for owner_id in &affected_owner_ids {
316 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
317 let updated: Vec<EntityId> =
318 rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
319 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
320 }
321 }
322
323 Ok(())
324 }
325
326 pub fn remove_multi(
327 &mut self,
328 event_buffer: &mut EventBuffer,
329 ids: &[EntityId],
330 ) -> Result<(), RepositoryError> {
331 let entities = self.table.get_multi(ids)?;
332 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
333 return Ok(());
334 }
335
336 let affected_owner_ids: Vec<EntityId> = {
338 let owner_repo = repository_factory::write::create_frame_repository(self.transaction)?;
339 owner_repo
340 .get_relationships_from_right_ids(&FrameRelationshipField::Blocks, ids)?
341 .into_iter()
342 .map(|(owner_id, _)| owner_id)
343 .collect()
344 };
345 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
347 std::collections::HashMap::new();
348 for owner_id in &affected_owner_ids {
349 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
350 }
351
352 self.table.remove_multi(ids)?;
353 event_buffer.push(Event {
354 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Removed)),
355 ids: ids.into(),
356 data: None,
357 });
358 {
360 let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
361 for owner_id in &affected_owner_ids {
362 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
363 let updated: Vec<EntityId> = rel_ids
364 .iter()
365 .copied()
366 .filter(|rid| !removed_set.contains(rid))
367 .collect();
368 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
369 }
370 }
371 }
372
373 Ok(())
374 }
375 pub fn get_relationship(
376 &self,
377 id: &EntityId,
378 field: &BlockRelationshipField,
379 ) -> Result<Vec<EntityId>, RepositoryError> {
380 self.table.get_relationship(id, field)
381 }
382 pub fn get_relationship_many(
383 &self,
384 ids: &[EntityId],
385 field: &BlockRelationshipField,
386 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
387 self.table.get_relationship_many(ids, field)
388 }
389 pub fn get_relationship_count(
390 &self,
391 id: &EntityId,
392 field: &BlockRelationshipField,
393 ) -> Result<usize, RepositoryError> {
394 self.table.get_relationship_count(id, field)
395 }
396 pub fn get_relationship_in_range(
397 &self,
398 id: &EntityId,
399 field: &BlockRelationshipField,
400 offset: usize,
401 limit: usize,
402 ) -> Result<Vec<EntityId>, RepositoryError> {
403 self.table
404 .get_relationship_in_range(id, field, offset, limit)
405 }
406 pub fn get_relationships_from_right_ids(
407 &self,
408 field: &BlockRelationshipField,
409 right_ids: &[EntityId],
410 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
411 self.table
412 .get_relationships_from_right_ids(field, right_ids)
413 }
414
415 pub fn set_relationship_multi(
416 &mut self,
417 event_buffer: &mut EventBuffer,
418 field: &BlockRelationshipField,
419 relationships: Vec<(EntityId, Vec<EntityId>)>,
420 ) -> Result<(), RepositoryError> {
421 let all_right_ids: Vec<EntityId> = relationships
423 .iter()
424 .flat_map(|(_, ids)| ids.iter().copied())
425 .collect();
426 if !all_right_ids.is_empty() {
427 match field {
428 BlockRelationshipField::List => {
429 let child_repo =
430 repository_factory::write::create_list_repository(self.transaction)?;
431 let found = child_repo.get_multi(&all_right_ids)?;
432 let missing: Vec<_> = all_right_ids
433 .iter()
434 .zip(found.iter())
435 .filter(|(_, entity)| entity.is_none())
436 .map(|(id, _)| *id)
437 .collect();
438 if !missing.is_empty() {
439 return Err(RepositoryError::MissingRelationshipTarget {
440 operation: "set_relationship_multi",
441 ids: missing,
442 });
443 }
444 }
445 }
446 }
447 self.table
448 .set_relationship_multi(field, relationships.clone())?;
449 for (left_id, right_ids) in relationships {
450 event_buffer.push(Event {
451 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Updated)),
452 ids: vec![left_id],
453 data: Some(format!(
454 "{}:{}",
455 field,
456 right_ids
457 .iter()
458 .map(|id| id.to_string())
459 .collect::<Vec<_>>()
460 .join(",")
461 )),
462 });
463 }
464 Ok(())
465 }
466
467 pub fn set_relationship(
468 &mut self,
469 event_buffer: &mut EventBuffer,
470 id: &EntityId,
471 field: &BlockRelationshipField,
472 right_ids: &[EntityId],
473 ) -> Result<(), RepositoryError> {
474 if !right_ids.is_empty() {
476 match field {
477 BlockRelationshipField::List => {
478 let child_repo =
479 repository_factory::write::create_list_repository(self.transaction)?;
480 let found = child_repo.get_multi(right_ids)?;
481 let missing: Vec<_> = right_ids
482 .iter()
483 .zip(found.iter())
484 .filter(|(_, entity)| entity.is_none())
485 .map(|(id, _)| *id)
486 .collect();
487 if !missing.is_empty() {
488 return Err(RepositoryError::MissingRelationshipTarget {
489 operation: "set_relationship",
490 ids: missing,
491 });
492 }
493 }
494 }
495 }
496 self.table.set_relationship(id, field, right_ids)?;
497 event_buffer.push(Event {
498 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Updated)),
499 ids: vec![*id],
500 data: Some(format!(
501 "{}:{}",
502 field,
503 right_ids
504 .iter()
505 .map(|id| id.to_string())
506 .collect::<Vec<_>>()
507 .join(",")
508 )),
509 });
510 Ok(())
511 }
512
513 pub fn move_relationship_ids(
514 &mut self,
515 event_buffer: &mut EventBuffer,
516 id: &EntityId,
517 field: &BlockRelationshipField,
518 ids_to_move: &[EntityId],
519 new_index: i32,
520 ) -> Result<Vec<EntityId>, RepositoryError> {
521 let reordered = self
522 .table
523 .move_relationship_ids(id, field, ids_to_move, new_index)?;
524 event_buffer.push(Event {
525 origin: Origin::DirectAccess(DirectAccessEntity::Block(EntityEvent::Updated)),
526 ids: vec![*id],
527 data: Some(format!(
528 "{}:{}",
529 field,
530 reordered
531 .iter()
532 .map(|id| id.to_string())
533 .collect::<Vec<_>>()
534 .join(",")
535 )),
536 });
537 Ok(reordered)
538 }
539 pub fn get_relationships_from_owner(
540 &self,
541 owner_id: &EntityId,
542 ) -> Result<Vec<EntityId>, RepositoryError> {
543 let repo = repository_factory::write::create_frame_repository(self.transaction)?;
544 repo.get_relationship(owner_id, &FrameRelationshipField::Blocks)
545 }
546
547 pub fn set_relationships_in_owner(
548 &mut self,
549 event_buffer: &mut EventBuffer,
550 owner_id: &EntityId,
551 ids: &[EntityId],
552 ) -> Result<(), RepositoryError> {
553 let mut repo = repository_factory::write::create_frame_repository(self.transaction)?;
554 repo.set_relationship(event_buffer, owner_id, &FrameRelationshipField::Blocks, ids)
555 }
556
557 pub fn snapshot(&self, _ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
558 let store_snap = self.transaction.snapshot_store();
559 Ok(EntityTreeSnapshot {
560 store_snapshot: Some(store_snap),
561 })
562 }
563
564 pub fn restore(
565 &mut self,
566 event_buffer: &mut EventBuffer,
567 snap: &EntityTreeSnapshot,
568 ) -> Result<(), RepositoryError> {
569 let store_snap = snap
570 .store_snapshot
571 .as_ref()
572 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
573 self.transaction.restore_store(store_snap);
574
575 let store = self.transaction.get_store();
576
577 let mut emit = |entity: DirectAccessEntity, ids: Vec<EntityId>| {
578 if !ids.is_empty() {
579 event_buffer.push(Event {
580 origin: Origin::DirectAccess(entity),
581 ids,
582 data: None,
583 });
584 }
585 };
586
587 let block_ids: Vec<_> = store.blocks.read().unwrap().keys().copied().collect();
589 emit(
590 DirectAccessEntity::Block(EntityEvent::Created),
591 block_ids.clone(),
592 );
593 emit(DirectAccessEntity::Block(EntityEvent::Updated), block_ids);
594
595 Ok(())
596 }
597}
598
599pub struct BlockRepositoryRO<'a> {
600 table: Box<dyn BlockTableRO + 'a>,
601}
602impl<'a> BlockRepositoryRO<'a> {
603 pub fn new(table: Box<dyn BlockTableRO + 'a>) -> Self {
604 BlockRepositoryRO { table }
605 }
606 pub fn get(&self, id: &EntityId) -> Result<Option<Block>, RepositoryError> {
607 self.table.get(id)
608 }
609 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Block>>, RepositoryError> {
610 self.table.get_multi(ids)
611 }
612 pub fn get_all(&self) -> Result<Vec<Block>, RepositoryError> {
613 self.table.get_all()
614 }
615 pub fn get_relationship(
616 &self,
617 id: &EntityId,
618 field: &BlockRelationshipField,
619 ) -> Result<Vec<EntityId>, RepositoryError> {
620 self.table.get_relationship(id, field)
621 }
622 pub fn get_relationship_many(
623 &self,
624 ids: &[EntityId],
625 field: &BlockRelationshipField,
626 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
627 self.table.get_relationship_many(ids, field)
628 }
629 pub fn get_relationship_count(
630 &self,
631 id: &EntityId,
632 field: &BlockRelationshipField,
633 ) -> Result<usize, RepositoryError> {
634 self.table.get_relationship_count(id, field)
635 }
636 pub fn get_relationship_in_range(
637 &self,
638 id: &EntityId,
639 field: &BlockRelationshipField,
640 offset: usize,
641 limit: usize,
642 ) -> Result<Vec<EntityId>, RepositoryError> {
643 self.table
644 .get_relationship_in_range(id, field, offset, limit)
645 }
646 pub fn get_relationships_from_right_ids(
647 &self,
648 field: &BlockRelationshipField,
649 right_ids: &[EntityId],
650 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
651 self.table
652 .get_relationships_from_right_ids(field, right_ids)
653 }
654}