Skip to main content

text_document_common/direct_access/root/
root_repository.rs

1// Generated by Qleany v1.5.0 from common_entity_repository.tera
2
3use std::fmt::Display;
4
5use crate::{
6    database::transactions::Transaction,
7    direct_access::repository_factory,
8    entities::Root,
9    event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10    snapshot::{EntityTreeSnapshot, TableLevelSnapshot},
11    types::EntityId,
12};
13
14use crate::error::RepositoryError;
15use serde::{Deserialize, Serialize};
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18pub enum RootRelationshipField {
19    Document,
20}
21
22impl Display for RootRelationshipField {
23    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
24        write!(f, "{:?}", self)
25    }
26}
27
28pub trait RootTable {
29    fn create(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
30    fn create_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError>;
31    fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError>;
32    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError>;
33    fn get_all(&self) -> Result<Vec<Root>, RepositoryError>;
34    fn update(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
35    fn update_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError>;
36    fn update_with_relationships(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
37    fn update_with_relationships_multi(
38        &mut self,
39        entities: &[Root],
40    ) -> Result<Vec<Root>, RepositoryError>;
41    fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
42    fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
43    fn get_relationship(
44        &self,
45        id: &EntityId,
46        field: &RootRelationshipField,
47    ) -> Result<Vec<EntityId>, RepositoryError>;
48    fn get_relationship_many(
49        &self,
50        ids: &[EntityId],
51        field: &RootRelationshipField,
52    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
53    fn get_relationship_count(
54        &self,
55        id: &EntityId,
56        field: &RootRelationshipField,
57    ) -> Result<usize, RepositoryError>;
58    fn get_relationship_in_range(
59        &self,
60        id: &EntityId,
61        field: &RootRelationshipField,
62        offset: usize,
63        limit: usize,
64    ) -> Result<Vec<EntityId>, RepositoryError>;
65    fn get_relationships_from_right_ids(
66        &self,
67        field: &RootRelationshipField,
68        right_ids: &[EntityId],
69    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
70    fn set_relationship_multi(
71        &mut self,
72        field: &RootRelationshipField,
73        relationships: Vec<(EntityId, Vec<EntityId>)>,
74    ) -> Result<(), RepositoryError>;
75    fn set_relationship(
76        &mut self,
77        id: &EntityId,
78        field: &RootRelationshipField,
79        right_ids: &[EntityId],
80    ) -> Result<(), RepositoryError>;
81    fn move_relationship_ids(
82        &mut self,
83        id: &EntityId,
84        field: &RootRelationshipField,
85        ids_to_move: &[EntityId],
86        new_index: i32,
87    ) -> Result<Vec<EntityId>, RepositoryError>;
88    fn snapshot_rows(&self, ids: &[EntityId]) -> Result<TableLevelSnapshot, RepositoryError>;
89    fn restore_rows(&mut self, snap: &TableLevelSnapshot) -> Result<(), RepositoryError>;
90}
91
92pub trait RootTableRO {
93    fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError>;
94    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError>;
95    fn get_all(&self) -> Result<Vec<Root>, RepositoryError>;
96    fn get_relationship(
97        &self,
98        id: &EntityId,
99        field: &RootRelationshipField,
100    ) -> Result<Vec<EntityId>, RepositoryError>;
101    fn get_relationship_many(
102        &self,
103        ids: &[EntityId],
104        field: &RootRelationshipField,
105    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
106    fn get_relationship_count(
107        &self,
108        id: &EntityId,
109        field: &RootRelationshipField,
110    ) -> Result<usize, RepositoryError>;
111    fn get_relationship_in_range(
112        &self,
113        id: &EntityId,
114        field: &RootRelationshipField,
115        offset: usize,
116        limit: usize,
117    ) -> Result<Vec<EntityId>, RepositoryError>;
118    fn get_relationships_from_right_ids(
119        &self,
120        field: &RootRelationshipField,
121        right_ids: &[EntityId],
122    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
123}
124
125pub struct RootRepository<'a> {
126    redb_table: Box<dyn RootTable + 'a>,
127    transaction: &'a Transaction,
128}
129
130impl<'a> RootRepository<'a> {
131    pub fn new(redb_table: Box<dyn RootTable + 'a>, transaction: &'a Transaction) -> Self {
132        RootRepository {
133            redb_table,
134            transaction,
135        }
136    }
137
138    pub fn create_orphan(
139        &mut self,
140        event_buffer: &mut EventBuffer,
141        entity: &Root,
142    ) -> Result<Root, RepositoryError> {
143        let new = self.redb_table.create(entity)?;
144        event_buffer.push(Event {
145            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Created)),
146            ids: vec![new.id],
147            data: None,
148        });
149        Ok(new)
150    }
151
152    pub fn create_orphan_multi(
153        &mut self,
154        event_buffer: &mut EventBuffer,
155        entities: &[Root],
156    ) -> Result<Vec<Root>, RepositoryError> {
157        let new_entities = self.redb_table.create_multi(entities)?;
158        event_buffer.push(Event {
159            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Created)),
160            ids: new_entities.iter().map(|e| e.id).collect(),
161            data: None,
162        });
163        Ok(new_entities)
164    }
165
166    pub fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
167        self.redb_table.get(id)
168    }
169    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
170        self.redb_table.get_multi(ids)
171    }
172    pub fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
173        self.redb_table.get_all()
174    }
175
176    pub fn update(
177        &mut self,
178        event_buffer: &mut EventBuffer,
179        entity: &Root,
180    ) -> Result<Root, RepositoryError> {
181        let updated = self.redb_table.update(entity)?;
182        event_buffer.push(Event {
183            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
184            ids: vec![updated.id],
185            data: None,
186        });
187        Ok(updated)
188    }
189
190    pub fn update_multi(
191        &mut self,
192        event_buffer: &mut EventBuffer,
193        entities: &[Root],
194    ) -> Result<Vec<Root>, RepositoryError> {
195        let updated = self.redb_table.update_multi(entities)?;
196        event_buffer.push(Event {
197            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
198            ids: updated.iter().map(|e| e.id).collect(),
199            data: None,
200        });
201        Ok(updated)
202    }
203
204    pub fn update_with_relationships(
205        &mut self,
206        event_buffer: &mut EventBuffer,
207        entity: &Root,
208    ) -> Result<Root, RepositoryError> {
209        let updated = self.redb_table.update_with_relationships(entity)?;
210        event_buffer.push(Event {
211            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
212            ids: vec![updated.id],
213            data: None,
214        });
215        Ok(updated)
216    }
217
218    pub fn update_with_relationships_multi(
219        &mut self,
220        event_buffer: &mut EventBuffer,
221        entities: &[Root],
222    ) -> Result<Vec<Root>, RepositoryError> {
223        let updated = self.redb_table.update_with_relationships_multi(entities)?;
224        event_buffer.push(Event {
225            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
226            ids: updated.iter().map(|e| e.id).collect(),
227            data: None,
228        });
229        Ok(updated)
230    }
231
232    pub fn remove(
233        &mut self,
234        event_buffer: &mut EventBuffer,
235        id: &EntityId,
236    ) -> Result<(), RepositoryError> {
237        let entity = match self.redb_table.get(id)? {
238            Some(e) => e,
239            None => return Ok(()),
240        };
241        // get all strong forward relationship fields
242
243        let document = entity.document;
244
245        // remove all strong relationships, initiating a cascade remove
246
247        repository_factory::write::create_document_repository(self.transaction)
248            .remove(event_buffer, &document)?;
249
250        // remove entity
251        self.redb_table.remove(id)?;
252        event_buffer.push(Event {
253            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Removed)),
254            ids: vec![*id],
255            data: None,
256        });
257
258        Ok(())
259    }
260
261    pub fn remove_multi(
262        &mut self,
263        event_buffer: &mut EventBuffer,
264        ids: &[EntityId],
265    ) -> Result<(), RepositoryError> {
266        let entities = self.redb_table.get_multi(ids)?;
267        if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
268            return Ok(());
269        }
270
271        // get all strong forward relationship fields
272
273        let document_ids: Vec<EntityId> = entities
274            .iter()
275            .filter_map(|entity| entity.as_ref().map(|entity| entity.document))
276            .collect();
277
278        // remove all strong relationships, initiating a cascade remove
279
280        repository_factory::write::create_document_repository(self.transaction)
281            .remove_multi(event_buffer, &document_ids)?;
282
283        self.redb_table.remove_multi(ids)?;
284        event_buffer.push(Event {
285            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Removed)),
286            ids: ids.into(),
287            data: None,
288        });
289
290        Ok(())
291    }
292    pub fn get_relationship(
293        &self,
294        id: &EntityId,
295        field: &RootRelationshipField,
296    ) -> Result<Vec<EntityId>, RepositoryError> {
297        self.redb_table.get_relationship(id, field)
298    }
299    pub fn get_relationship_many(
300        &self,
301        ids: &[EntityId],
302        field: &RootRelationshipField,
303    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
304        self.redb_table.get_relationship_many(ids, field)
305    }
306    pub fn get_relationship_count(
307        &self,
308        id: &EntityId,
309        field: &RootRelationshipField,
310    ) -> Result<usize, RepositoryError> {
311        self.redb_table.get_relationship_count(id, field)
312    }
313    pub fn get_relationship_in_range(
314        &self,
315        id: &EntityId,
316        field: &RootRelationshipField,
317        offset: usize,
318        limit: usize,
319    ) -> Result<Vec<EntityId>, RepositoryError> {
320        self.redb_table
321            .get_relationship_in_range(id, field, offset, limit)
322    }
323    pub fn get_relationships_from_right_ids(
324        &self,
325        field: &RootRelationshipField,
326        right_ids: &[EntityId],
327    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
328        self.redb_table
329            .get_relationships_from_right_ids(field, right_ids)
330    }
331
332    pub fn set_relationship_multi(
333        &mut self,
334        event_buffer: &mut EventBuffer,
335        field: &RootRelationshipField,
336        relationships: Vec<(EntityId, Vec<EntityId>)>,
337    ) -> Result<(), RepositoryError> {
338        // Validate that all right_ids exist
339        let all_right_ids: Vec<EntityId> = relationships
340            .iter()
341            .flat_map(|(_, ids)| ids.iter().copied())
342            .collect();
343        if !all_right_ids.is_empty() {
344            match field {
345                RootRelationshipField::Document => {
346                    let child_repo =
347                        repository_factory::write::create_document_repository(self.transaction);
348                    let found = child_repo.get_multi(&all_right_ids)?;
349                    let missing: Vec<_> = all_right_ids
350                        .iter()
351                        .zip(found.iter())
352                        .filter(|(_, entity)| entity.is_none())
353                        .map(|(id, _)| *id)
354                        .collect();
355                    if !missing.is_empty() {
356                        return Err(RepositoryError::MissingRelationshipTarget {
357                            operation: "set_relationship_multi",
358                            ids: missing,
359                        });
360                    }
361                }
362            }
363        }
364        self.redb_table
365            .set_relationship_multi(field, relationships.clone())?;
366        for (left_id, right_ids) in relationships {
367            event_buffer.push(Event {
368                origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
369                ids: vec![left_id],
370                data: Some(format!(
371                    "{}:{}",
372                    field,
373                    right_ids
374                        .iter()
375                        .map(|id| id.to_string())
376                        .collect::<Vec<_>>()
377                        .join(",")
378                )),
379            });
380        }
381        Ok(())
382    }
383
384    pub fn set_relationship(
385        &mut self,
386        event_buffer: &mut EventBuffer,
387        id: &EntityId,
388        field: &RootRelationshipField,
389        right_ids: &[EntityId],
390    ) -> Result<(), RepositoryError> {
391        // Validate that all right_ids exist
392        if !right_ids.is_empty() {
393            match field {
394                RootRelationshipField::Document => {
395                    let child_repo =
396                        repository_factory::write::create_document_repository(self.transaction);
397                    let found = child_repo.get_multi(right_ids)?;
398                    let missing: Vec<_> = right_ids
399                        .iter()
400                        .zip(found.iter())
401                        .filter(|(_, entity)| entity.is_none())
402                        .map(|(id, _)| *id)
403                        .collect();
404                    if !missing.is_empty() {
405                        return Err(RepositoryError::MissingRelationshipTarget {
406                            operation: "set_relationship",
407                            ids: missing,
408                        });
409                    }
410                }
411            }
412        }
413        self.redb_table.set_relationship(id, field, right_ids)?;
414        event_buffer.push(Event {
415            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
416            ids: vec![*id],
417            data: Some(format!(
418                "{}:{}",
419                field,
420                right_ids
421                    .iter()
422                    .map(|id| id.to_string())
423                    .collect::<Vec<_>>()
424                    .join(",")
425            )),
426        });
427        Ok(())
428    }
429
430    pub fn move_relationship_ids(
431        &mut self,
432        event_buffer: &mut EventBuffer,
433        id: &EntityId,
434        field: &RootRelationshipField,
435        ids_to_move: &[EntityId],
436        new_index: i32,
437    ) -> Result<Vec<EntityId>, RepositoryError> {
438        let reordered = self
439            .redb_table
440            .move_relationship_ids(id, field, ids_to_move, new_index)?;
441        event_buffer.push(Event {
442            origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
443            ids: vec![*id],
444            data: Some(format!(
445                "{}:{}",
446                field,
447                reordered
448                    .iter()
449                    .map(|id| id.to_string())
450                    .collect::<Vec<_>>()
451                    .join(",")
452            )),
453        });
454        Ok(reordered)
455    }
456
457    pub fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
458        let table_data = self.redb_table.snapshot_rows(ids)?;
459
460        // Recursively snapshot strong children
461        #[allow(unused_mut)]
462        let mut children = Vec::new();
463
464        {
465            // Extract child IDs from the forward junction snapshot for document
466            let junction_name = "document_from_root_document_junction";
467            let child_ids: Vec<EntityId> = table_data
468                .forward_junctions
469                .iter()
470                .filter(|j| j.table_name == junction_name)
471                .flat_map(|j| {
472                    j.entries
473                        .iter()
474                        .flat_map(|(_, right_ids)| right_ids.iter().copied())
475                })
476                .collect();
477            if !child_ids.is_empty() {
478                let child_repo =
479                    repository_factory::write::create_document_repository(self.transaction);
480                children.push(child_repo.snapshot(&child_ids)?);
481            }
482        }
483
484        Ok(EntityTreeSnapshot {
485            table_data,
486            children,
487        })
488    }
489
490    pub fn restore(
491        &mut self,
492        event_buffer: &mut EventBuffer,
493        snap: &EntityTreeSnapshot,
494    ) -> Result<(), RepositoryError> {
495        // Restore children first (bottom-up)
496
497        for child_snap in &snap.children {
498            if child_snap.table_data.entity_rows.table_name == "document" {
499                repository_factory::write::create_document_repository(self.transaction)
500                    .restore(event_buffer, child_snap)?;
501            }
502        }
503
504        // Restore this entity's rows
505        self.redb_table.restore_rows(&snap.table_data)?;
506
507        // Emit Created events for restored entity IDs
508        let restored_ids: Vec<EntityId> = snap
509            .table_data
510            .entity_rows
511            .rows
512            .iter()
513            .map(|(id, _)| *id)
514            .collect();
515        if !restored_ids.is_empty() {
516            event_buffer.push(Event {
517                origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Created)),
518                ids: restored_ids.clone(),
519                data: None,
520            });
521        }
522        // Emit Updated events for restored relationships
523        if !restored_ids.is_empty() {
524            event_buffer.push(Event {
525                origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
526                ids: restored_ids,
527                data: None,
528            });
529        }
530        Ok(())
531    }
532}
533
534pub struct RootRepositoryRO<'a> {
535    redb_table: Box<dyn RootTableRO + 'a>,
536}
537impl<'a> RootRepositoryRO<'a> {
538    pub fn new(redb_table: Box<dyn RootTableRO + 'a>) -> Self {
539        RootRepositoryRO { redb_table }
540    }
541    pub fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
542        self.redb_table.get(id)
543    }
544    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
545        self.redb_table.get_multi(ids)
546    }
547    pub fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
548        self.redb_table.get_all()
549    }
550    pub fn get_relationship(
551        &self,
552        id: &EntityId,
553        field: &RootRelationshipField,
554    ) -> Result<Vec<EntityId>, RepositoryError> {
555        self.redb_table.get_relationship(id, field)
556    }
557    pub fn get_relationship_many(
558        &self,
559        ids: &[EntityId],
560        field: &RootRelationshipField,
561    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
562        self.redb_table.get_relationship_many(ids, field)
563    }
564    pub fn get_relationship_count(
565        &self,
566        id: &EntityId,
567        field: &RootRelationshipField,
568    ) -> Result<usize, RepositoryError> {
569        self.redb_table.get_relationship_count(id, field)
570    }
571    pub fn get_relationship_in_range(
572        &self,
573        id: &EntityId,
574        field: &RootRelationshipField,
575        offset: usize,
576        limit: usize,
577    ) -> Result<Vec<EntityId>, RepositoryError> {
578        self.redb_table
579            .get_relationship_in_range(id, field, offset, limit)
580    }
581    pub fn get_relationships_from_right_ids(
582        &self,
583        field: &RootRelationshipField,
584        right_ids: &[EntityId],
585    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
586        self.redb_table
587            .get_relationships_from_right_ids(field, right_ids)
588    }
589}