Skip to main content

common/direct_access/block/
block_repository.rs

1// Generated by Qleany v1.7.3 from common_entity_repository.tera
2
3use 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        // Insert at index
173        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        // Before removal, find which owner(s) reference this entity
292        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        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
301        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        // remove entity
308        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        // Update each affected owner's relationship to exclude removed ID (emits Updated event)
315        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        // Before removal, find which owner(s) reference these entities
337        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        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
346        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        // Update each affected owner's relationship to exclude removed IDs (emits Updated event)
359        {
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        // Validate that all right_ids exist
422        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        // Validate that all right_ids exist
475        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        // Emit Created events for this entity
588        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}