Skip to main content

text_document_common/direct_access/document/
document_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::Document,
9    event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10    snapshot::{EntityTreeSnapshot, TableLevelSnapshot},
11    types::EntityId,
12};
13
14use crate::direct_access::root::RootRelationshipField;
15use crate::error::RepositoryError;
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum DocumentRelationshipField {
20    Frames,
21    Lists,
22    Resources,
23}
24
25impl Display for DocumentRelationshipField {
26    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
27        write!(f, "{:?}", self)
28    }
29}
30
31pub trait DocumentTable {
32    fn create(&mut self, entity: &Document) -> Result<Document, RepositoryError>;
33    fn create_multi(&mut self, entities: &[Document]) -> Result<Vec<Document>, RepositoryError>;
34    fn get(&self, id: &EntityId) -> Result<Option<Document>, RepositoryError>;
35    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Document>>, RepositoryError>;
36    fn get_all(&self) -> Result<Vec<Document>, RepositoryError>;
37    fn update(&mut self, entity: &Document) -> Result<Document, RepositoryError>;
38    fn update_multi(&mut self, entities: &[Document]) -> Result<Vec<Document>, RepositoryError>;
39    fn update_with_relationships(&mut self, entity: &Document)
40    -> Result<Document, RepositoryError>;
41    fn update_with_relationships_multi(
42        &mut self,
43        entities: &[Document],
44    ) -> Result<Vec<Document>, RepositoryError>;
45    fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
46    fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
47    fn get_relationship(
48        &self,
49        id: &EntityId,
50        field: &DocumentRelationshipField,
51    ) -> Result<Vec<EntityId>, RepositoryError>;
52    fn get_relationship_many(
53        &self,
54        ids: &[EntityId],
55        field: &DocumentRelationshipField,
56    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
57    fn get_relationship_count(
58        &self,
59        id: &EntityId,
60        field: &DocumentRelationshipField,
61    ) -> Result<usize, RepositoryError>;
62    fn get_relationship_in_range(
63        &self,
64        id: &EntityId,
65        field: &DocumentRelationshipField,
66        offset: usize,
67        limit: usize,
68    ) -> Result<Vec<EntityId>, RepositoryError>;
69    fn get_relationships_from_right_ids(
70        &self,
71        field: &DocumentRelationshipField,
72        right_ids: &[EntityId],
73    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
74    fn set_relationship_multi(
75        &mut self,
76        field: &DocumentRelationshipField,
77        relationships: Vec<(EntityId, Vec<EntityId>)>,
78    ) -> Result<(), RepositoryError>;
79    fn set_relationship(
80        &mut self,
81        id: &EntityId,
82        field: &DocumentRelationshipField,
83        right_ids: &[EntityId],
84    ) -> Result<(), RepositoryError>;
85    fn move_relationship_ids(
86        &mut self,
87        id: &EntityId,
88        field: &DocumentRelationshipField,
89        ids_to_move: &[EntityId],
90        new_index: i32,
91    ) -> Result<Vec<EntityId>, RepositoryError>;
92    fn snapshot_rows(&self, ids: &[EntityId]) -> Result<TableLevelSnapshot, RepositoryError>;
93    fn restore_rows(&mut self, snap: &TableLevelSnapshot) -> Result<(), RepositoryError>;
94}
95
96pub trait DocumentTableRO {
97    fn get(&self, id: &EntityId) -> Result<Option<Document>, RepositoryError>;
98    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Document>>, RepositoryError>;
99    fn get_all(&self) -> Result<Vec<Document>, RepositoryError>;
100    fn get_relationship(
101        &self,
102        id: &EntityId,
103        field: &DocumentRelationshipField,
104    ) -> Result<Vec<EntityId>, RepositoryError>;
105    fn get_relationship_many(
106        &self,
107        ids: &[EntityId],
108        field: &DocumentRelationshipField,
109    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
110    fn get_relationship_count(
111        &self,
112        id: &EntityId,
113        field: &DocumentRelationshipField,
114    ) -> Result<usize, RepositoryError>;
115    fn get_relationship_in_range(
116        &self,
117        id: &EntityId,
118        field: &DocumentRelationshipField,
119        offset: usize,
120        limit: usize,
121    ) -> Result<Vec<EntityId>, RepositoryError>;
122    fn get_relationships_from_right_ids(
123        &self,
124        field: &DocumentRelationshipField,
125        right_ids: &[EntityId],
126    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
127}
128
129pub struct DocumentRepository<'a> {
130    redb_table: Box<dyn DocumentTable + 'a>,
131    transaction: &'a Transaction,
132}
133
134impl<'a> DocumentRepository<'a> {
135    pub fn new(redb_table: Box<dyn DocumentTable + 'a>, transaction: &'a Transaction) -> Self {
136        DocumentRepository {
137            redb_table,
138            transaction,
139        }
140    }
141
142    pub fn create_orphan(
143        &mut self,
144        event_buffer: &mut EventBuffer,
145        entity: &Document,
146    ) -> Result<Document, RepositoryError> {
147        let new = self.redb_table.create(entity)?;
148        event_buffer.push(Event {
149            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Created)),
150            ids: vec![new.id],
151            data: None,
152        });
153        Ok(new)
154    }
155
156    pub fn create_orphan_multi(
157        &mut self,
158        event_buffer: &mut EventBuffer,
159        entities: &[Document],
160    ) -> Result<Vec<Document>, RepositoryError> {
161        let new_entities = self.redb_table.create_multi(entities)?;
162        event_buffer.push(Event {
163            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Created)),
164            ids: new_entities.iter().map(|e| e.id).collect(),
165            data: None,
166        });
167        Ok(new_entities)
168    }
169    pub fn create(
170        &mut self,
171        event_buffer: &mut EventBuffer,
172        entity: &Document,
173        owner_id: EntityId,
174        _index: i32,
175    ) -> Result<Document, RepositoryError> {
176        let new = self.redb_table.create(entity)?;
177        let created_id = new.id;
178
179        let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
180        if relationship_ids.is_empty() {
181            relationship_ids = vec![created_id];
182        } else {
183            // Replace existing relationship: cascade-remove old entities first
184            self.remove_multi(event_buffer, &relationship_ids)?;
185            relationship_ids = vec![created_id];
186        }
187
188        self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
189        event_buffer.push(Event {
190            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Created)),
191            ids: vec![created_id],
192            data: None,
193        });
194        Ok(new)
195    }
196
197    pub fn create_multi(
198        &mut self,
199        event_buffer: &mut EventBuffer,
200        entities: &[Document],
201        owner_id: EntityId,
202        _index: i32,
203    ) -> Result<Vec<Document>, RepositoryError> {
204        let new_entities = self.redb_table.create_multi(entities)?;
205        let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
206
207        let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
208        if relationship_ids.is_empty() {
209            relationship_ids = created_ids.clone();
210        } else {
211            self.remove_multi(event_buffer, &relationship_ids)?;
212            relationship_ids = created_ids.clone();
213        }
214
215        self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
216        event_buffer.push(Event {
217            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Created)),
218            ids: created_ids,
219            data: None,
220        });
221        Ok(new_entities)
222    }
223
224    pub fn get(&self, id: &EntityId) -> Result<Option<Document>, RepositoryError> {
225        self.redb_table.get(id)
226    }
227    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Document>>, RepositoryError> {
228        self.redb_table.get_multi(ids)
229    }
230    pub fn get_all(&self) -> Result<Vec<Document>, RepositoryError> {
231        self.redb_table.get_all()
232    }
233
234    pub fn update(
235        &mut self,
236        event_buffer: &mut EventBuffer,
237        entity: &Document,
238    ) -> Result<Document, RepositoryError> {
239        let updated = self.redb_table.update(entity)?;
240        event_buffer.push(Event {
241            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Updated)),
242            ids: vec![updated.id],
243            data: None,
244        });
245        Ok(updated)
246    }
247
248    pub fn update_multi(
249        &mut self,
250        event_buffer: &mut EventBuffer,
251        entities: &[Document],
252    ) -> Result<Vec<Document>, RepositoryError> {
253        let updated = self.redb_table.update_multi(entities)?;
254        event_buffer.push(Event {
255            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Updated)),
256            ids: updated.iter().map(|e| e.id).collect(),
257            data: None,
258        });
259        Ok(updated)
260    }
261
262    pub fn update_with_relationships(
263        &mut self,
264        event_buffer: &mut EventBuffer,
265        entity: &Document,
266    ) -> Result<Document, RepositoryError> {
267        let updated = self.redb_table.update_with_relationships(entity)?;
268        event_buffer.push(Event {
269            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Updated)),
270            ids: vec![updated.id],
271            data: None,
272        });
273        Ok(updated)
274    }
275
276    pub fn update_with_relationships_multi(
277        &mut self,
278        event_buffer: &mut EventBuffer,
279        entities: &[Document],
280    ) -> Result<Vec<Document>, RepositoryError> {
281        let updated = self.redb_table.update_with_relationships_multi(entities)?;
282        event_buffer.push(Event {
283            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Updated)),
284            ids: updated.iter().map(|e| e.id).collect(),
285            data: None,
286        });
287        Ok(updated)
288    }
289
290    pub fn remove(
291        &mut self,
292        event_buffer: &mut EventBuffer,
293        id: &EntityId,
294    ) -> Result<(), RepositoryError> {
295        let entity = match self.redb_table.get(id)? {
296            Some(e) => e,
297            None => return Ok(()),
298        };
299        // get all strong forward relationship fields
300
301        let frames = entity.frames.clone();
302        let resources = entity.resources.clone();
303        let lists = entity.lists.clone();
304
305        // remove all strong relationships, initiating a cascade remove
306
307        repository_factory::write::create_frame_repository(self.transaction)
308            .remove_multi(event_buffer, &frames)?;
309        repository_factory::write::create_resource_repository(self.transaction)
310            .remove_multi(event_buffer, &resources)?;
311        repository_factory::write::create_list_repository(self.transaction)
312            .remove_multi(event_buffer, &lists)?;
313        // Before removal, find which owner(s) reference this entity
314        let affected_owner_ids: Vec<EntityId> = {
315            let owner_repo = repository_factory::write::create_root_repository(self.transaction);
316            owner_repo
317                .get_relationships_from_right_ids(&RootRelationshipField::Document, &[*id])?
318                .into_iter()
319                .map(|(owner_id, _)| owner_id)
320                .collect()
321        };
322        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
323        let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
324            std::collections::HashMap::new();
325        for owner_id in &affected_owner_ids {
326            owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
327        }
328
329        // remove entity
330        self.redb_table.remove(id)?;
331        event_buffer.push(Event {
332            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Removed)),
333            ids: vec![*id],
334            data: None,
335        });
336        // Update each affected owner's relationship to exclude removed ID (emits Updated event)
337        for owner_id in &affected_owner_ids {
338            if let Some(rel_ids) = owner_rel_before.get(owner_id) {
339                let updated: Vec<EntityId> =
340                    rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
341                self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
342            }
343        }
344
345        Ok(())
346    }
347
348    pub fn remove_multi(
349        &mut self,
350        event_buffer: &mut EventBuffer,
351        ids: &[EntityId],
352    ) -> Result<(), RepositoryError> {
353        let entities = self.redb_table.get_multi(ids)?;
354        if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
355            return Ok(());
356        }
357
358        // get all strong forward relationship fields
359
360        let mut frames_ids: Vec<EntityId> = entities
361            .iter()
362            .flat_map(|entity| entity.as_ref().map(|entity| entity.frames.clone()))
363            .flatten()
364            .collect();
365        // remove duplicates
366        frames_ids.sort();
367        frames_ids.dedup();
368        let mut resources_ids: Vec<EntityId> = entities
369            .iter()
370            .flat_map(|entity| entity.as_ref().map(|entity| entity.resources.clone()))
371            .flatten()
372            .collect();
373        // remove duplicates
374        resources_ids.sort();
375        resources_ids.dedup();
376        let mut lists_ids: Vec<EntityId> = entities
377            .iter()
378            .flat_map(|entity| entity.as_ref().map(|entity| entity.lists.clone()))
379            .flatten()
380            .collect();
381        // remove duplicates
382        lists_ids.sort();
383        lists_ids.dedup();
384
385        // remove all strong relationships, initiating a cascade remove
386
387        repository_factory::write::create_frame_repository(self.transaction)
388            .remove_multi(event_buffer, &frames_ids)?;
389        repository_factory::write::create_resource_repository(self.transaction)
390            .remove_multi(event_buffer, &resources_ids)?;
391        repository_factory::write::create_list_repository(self.transaction)
392            .remove_multi(event_buffer, &lists_ids)?;
393        // Before removal, find which owner(s) reference these entities
394        let affected_owner_ids: Vec<EntityId> = {
395            let owner_repo = repository_factory::write::create_root_repository(self.transaction);
396            owner_repo
397                .get_relationships_from_right_ids(&RootRelationshipField::Document, ids)?
398                .into_iter()
399                .map(|(owner_id, _)| owner_id)
400                .collect()
401        };
402        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
403        let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
404            std::collections::HashMap::new();
405        for owner_id in &affected_owner_ids {
406            owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
407        }
408
409        self.redb_table.remove_multi(ids)?;
410        event_buffer.push(Event {
411            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Removed)),
412            ids: ids.into(),
413            data: None,
414        });
415        // Update each affected owner's relationship to exclude removed IDs (emits Updated event)
416        {
417            let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
418            for owner_id in &affected_owner_ids {
419                if let Some(rel_ids) = owner_rel_before.get(owner_id) {
420                    let updated: Vec<EntityId> = rel_ids
421                        .iter()
422                        .copied()
423                        .filter(|rid| !removed_set.contains(rid))
424                        .collect();
425                    self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
426                }
427            }
428        }
429
430        Ok(())
431    }
432    pub fn get_relationship(
433        &self,
434        id: &EntityId,
435        field: &DocumentRelationshipField,
436    ) -> Result<Vec<EntityId>, RepositoryError> {
437        self.redb_table.get_relationship(id, field)
438    }
439    pub fn get_relationship_many(
440        &self,
441        ids: &[EntityId],
442        field: &DocumentRelationshipField,
443    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
444        self.redb_table.get_relationship_many(ids, field)
445    }
446    pub fn get_relationship_count(
447        &self,
448        id: &EntityId,
449        field: &DocumentRelationshipField,
450    ) -> Result<usize, RepositoryError> {
451        self.redb_table.get_relationship_count(id, field)
452    }
453    pub fn get_relationship_in_range(
454        &self,
455        id: &EntityId,
456        field: &DocumentRelationshipField,
457        offset: usize,
458        limit: usize,
459    ) -> Result<Vec<EntityId>, RepositoryError> {
460        self.redb_table
461            .get_relationship_in_range(id, field, offset, limit)
462    }
463    pub fn get_relationships_from_right_ids(
464        &self,
465        field: &DocumentRelationshipField,
466        right_ids: &[EntityId],
467    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
468        self.redb_table
469            .get_relationships_from_right_ids(field, right_ids)
470    }
471
472    pub fn set_relationship_multi(
473        &mut self,
474        event_buffer: &mut EventBuffer,
475        field: &DocumentRelationshipField,
476        relationships: Vec<(EntityId, Vec<EntityId>)>,
477    ) -> Result<(), RepositoryError> {
478        // Validate that all right_ids exist
479        let all_right_ids: Vec<EntityId> = relationships
480            .iter()
481            .flat_map(|(_, ids)| ids.iter().copied())
482            .collect();
483        if !all_right_ids.is_empty() {
484            match field {
485                DocumentRelationshipField::Frames => {
486                    let child_repo =
487                        repository_factory::write::create_frame_repository(self.transaction);
488                    let found = child_repo.get_multi(&all_right_ids)?;
489                    let missing: Vec<_> = all_right_ids
490                        .iter()
491                        .zip(found.iter())
492                        .filter(|(_, entity)| entity.is_none())
493                        .map(|(id, _)| *id)
494                        .collect();
495                    if !missing.is_empty() {
496                        return Err(RepositoryError::MissingRelationshipTarget {
497                            operation: "set_relationship_multi",
498                            ids: missing,
499                        });
500                    }
501                }
502                DocumentRelationshipField::Lists => {
503                    let child_repo =
504                        repository_factory::write::create_list_repository(self.transaction);
505                    let found = child_repo.get_multi(&all_right_ids)?;
506                    let missing: Vec<_> = all_right_ids
507                        .iter()
508                        .zip(found.iter())
509                        .filter(|(_, entity)| entity.is_none())
510                        .map(|(id, _)| *id)
511                        .collect();
512                    if !missing.is_empty() {
513                        return Err(RepositoryError::MissingRelationshipTarget {
514                            operation: "set_relationship_multi",
515                            ids: missing,
516                        });
517                    }
518                }
519                DocumentRelationshipField::Resources => {
520                    let child_repo =
521                        repository_factory::write::create_resource_repository(self.transaction);
522                    let found = child_repo.get_multi(&all_right_ids)?;
523                    let missing: Vec<_> = all_right_ids
524                        .iter()
525                        .zip(found.iter())
526                        .filter(|(_, entity)| entity.is_none())
527                        .map(|(id, _)| *id)
528                        .collect();
529                    if !missing.is_empty() {
530                        return Err(RepositoryError::MissingRelationshipTarget {
531                            operation: "set_relationship_multi",
532                            ids: missing,
533                        });
534                    }
535                }
536            }
537        }
538        self.redb_table
539            .set_relationship_multi(field, relationships.clone())?;
540        for (left_id, right_ids) in relationships {
541            event_buffer.push(Event {
542                origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Updated)),
543                ids: vec![left_id],
544                data: Some(format!(
545                    "{}:{}",
546                    field,
547                    right_ids
548                        .iter()
549                        .map(|id| id.to_string())
550                        .collect::<Vec<_>>()
551                        .join(",")
552                )),
553            });
554        }
555        Ok(())
556    }
557
558    pub fn set_relationship(
559        &mut self,
560        event_buffer: &mut EventBuffer,
561        id: &EntityId,
562        field: &DocumentRelationshipField,
563        right_ids: &[EntityId],
564    ) -> Result<(), RepositoryError> {
565        // Validate that all right_ids exist
566        if !right_ids.is_empty() {
567            match field {
568                DocumentRelationshipField::Frames => {
569                    let child_repo =
570                        repository_factory::write::create_frame_repository(self.transaction);
571                    let found = child_repo.get_multi(right_ids)?;
572                    let missing: Vec<_> = right_ids
573                        .iter()
574                        .zip(found.iter())
575                        .filter(|(_, entity)| entity.is_none())
576                        .map(|(id, _)| *id)
577                        .collect();
578                    if !missing.is_empty() {
579                        return Err(RepositoryError::MissingRelationshipTarget {
580                            operation: "set_relationship",
581                            ids: missing,
582                        });
583                    }
584                }
585                DocumentRelationshipField::Lists => {
586                    let child_repo =
587                        repository_factory::write::create_list_repository(self.transaction);
588                    let found = child_repo.get_multi(right_ids)?;
589                    let missing: Vec<_> = right_ids
590                        .iter()
591                        .zip(found.iter())
592                        .filter(|(_, entity)| entity.is_none())
593                        .map(|(id, _)| *id)
594                        .collect();
595                    if !missing.is_empty() {
596                        return Err(RepositoryError::MissingRelationshipTarget {
597                            operation: "set_relationship",
598                            ids: missing,
599                        });
600                    }
601                }
602                DocumentRelationshipField::Resources => {
603                    let child_repo =
604                        repository_factory::write::create_resource_repository(self.transaction);
605                    let found = child_repo.get_multi(right_ids)?;
606                    let missing: Vec<_> = right_ids
607                        .iter()
608                        .zip(found.iter())
609                        .filter(|(_, entity)| entity.is_none())
610                        .map(|(id, _)| *id)
611                        .collect();
612                    if !missing.is_empty() {
613                        return Err(RepositoryError::MissingRelationshipTarget {
614                            operation: "set_relationship",
615                            ids: missing,
616                        });
617                    }
618                }
619            }
620        }
621        self.redb_table.set_relationship(id, field, right_ids)?;
622        event_buffer.push(Event {
623            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Updated)),
624            ids: vec![*id],
625            data: Some(format!(
626                "{}:{}",
627                field,
628                right_ids
629                    .iter()
630                    .map(|id| id.to_string())
631                    .collect::<Vec<_>>()
632                    .join(",")
633            )),
634        });
635        Ok(())
636    }
637
638    pub fn move_relationship_ids(
639        &mut self,
640        event_buffer: &mut EventBuffer,
641        id: &EntityId,
642        field: &DocumentRelationshipField,
643        ids_to_move: &[EntityId],
644        new_index: i32,
645    ) -> Result<Vec<EntityId>, RepositoryError> {
646        let reordered = self
647            .redb_table
648            .move_relationship_ids(id, field, ids_to_move, new_index)?;
649        event_buffer.push(Event {
650            origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Updated)),
651            ids: vec![*id],
652            data: Some(format!(
653                "{}:{}",
654                field,
655                reordered
656                    .iter()
657                    .map(|id| id.to_string())
658                    .collect::<Vec<_>>()
659                    .join(",")
660            )),
661        });
662        Ok(reordered)
663    }
664    pub fn get_relationships_from_owner(
665        &self,
666        owner_id: &EntityId,
667    ) -> Result<Vec<EntityId>, RepositoryError> {
668        let repo = repository_factory::write::create_root_repository(self.transaction);
669        repo.get_relationship(owner_id, &RootRelationshipField::Document)
670    }
671
672    pub fn set_relationships_in_owner(
673        &mut self,
674        event_buffer: &mut EventBuffer,
675        owner_id: &EntityId,
676        ids: &[EntityId],
677    ) -> Result<(), RepositoryError> {
678        let mut repo = repository_factory::write::create_root_repository(self.transaction);
679        repo.set_relationship(
680            event_buffer,
681            owner_id,
682            &RootRelationshipField::Document,
683            ids,
684        )
685    }
686
687    pub fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
688        let table_data = self.redb_table.snapshot_rows(ids)?;
689
690        // Recursively snapshot strong children
691        #[allow(unused_mut)]
692        let mut children = Vec::new();
693
694        {
695            // Extract child IDs from the forward junction snapshot for frames
696            let junction_name = "frame_from_document_frames_junction";
697            let child_ids: Vec<EntityId> = table_data
698                .forward_junctions
699                .iter()
700                .filter(|j| j.table_name == junction_name)
701                .flat_map(|j| {
702                    j.entries
703                        .iter()
704                        .flat_map(|(_, right_ids)| right_ids.iter().copied())
705                })
706                .collect();
707            if !child_ids.is_empty() {
708                let child_repo =
709                    repository_factory::write::create_frame_repository(self.transaction);
710                children.push(child_repo.snapshot(&child_ids)?);
711            }
712        }
713        {
714            // Extract child IDs from the forward junction snapshot for resources
715            let junction_name = "resource_from_document_resources_junction";
716            let child_ids: Vec<EntityId> = table_data
717                .forward_junctions
718                .iter()
719                .filter(|j| j.table_name == junction_name)
720                .flat_map(|j| {
721                    j.entries
722                        .iter()
723                        .flat_map(|(_, right_ids)| right_ids.iter().copied())
724                })
725                .collect();
726            if !child_ids.is_empty() {
727                let child_repo =
728                    repository_factory::write::create_resource_repository(self.transaction);
729                children.push(child_repo.snapshot(&child_ids)?);
730            }
731        }
732        {
733            // Extract child IDs from the forward junction snapshot for lists
734            let junction_name = "list_from_document_lists_junction";
735            let child_ids: Vec<EntityId> = table_data
736                .forward_junctions
737                .iter()
738                .filter(|j| j.table_name == junction_name)
739                .flat_map(|j| {
740                    j.entries
741                        .iter()
742                        .flat_map(|(_, right_ids)| right_ids.iter().copied())
743                })
744                .collect();
745            if !child_ids.is_empty() {
746                let child_repo =
747                    repository_factory::write::create_list_repository(self.transaction);
748                children.push(child_repo.snapshot(&child_ids)?);
749            }
750        }
751
752        Ok(EntityTreeSnapshot {
753            table_data,
754            children,
755        })
756    }
757
758    pub fn restore(
759        &mut self,
760        event_buffer: &mut EventBuffer,
761        snap: &EntityTreeSnapshot,
762    ) -> Result<(), RepositoryError> {
763        // Restore children first (bottom-up)
764
765        for child_snap in &snap.children {
766            if child_snap.table_data.entity_rows.table_name == "frame" {
767                repository_factory::write::create_frame_repository(self.transaction)
768                    .restore(event_buffer, child_snap)?;
769            }
770        }
771        for child_snap in &snap.children {
772            if child_snap.table_data.entity_rows.table_name == "resource" {
773                repository_factory::write::create_resource_repository(self.transaction)
774                    .restore(event_buffer, child_snap)?;
775            }
776        }
777        for child_snap in &snap.children {
778            if child_snap.table_data.entity_rows.table_name == "list" {
779                repository_factory::write::create_list_repository(self.transaction)
780                    .restore(event_buffer, child_snap)?;
781            }
782        }
783
784        // Restore this entity's rows
785        self.redb_table.restore_rows(&snap.table_data)?;
786
787        // Emit Created events for restored entity IDs
788        let restored_ids: Vec<EntityId> = snap
789            .table_data
790            .entity_rows
791            .rows
792            .iter()
793            .map(|(id, _)| *id)
794            .collect();
795        if !restored_ids.is_empty() {
796            event_buffer.push(Event {
797                origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Created)),
798                ids: restored_ids.clone(),
799                data: None,
800            });
801        }
802        // Emit Updated events for restored relationships
803        if !restored_ids.is_empty() {
804            event_buffer.push(Event {
805                origin: Origin::DirectAccess(DirectAccessEntity::Document(EntityEvent::Updated)),
806                ids: restored_ids,
807                data: None,
808            });
809        }
810        Ok(())
811    }
812}
813
814pub struct DocumentRepositoryRO<'a> {
815    redb_table: Box<dyn DocumentTableRO + 'a>,
816}
817impl<'a> DocumentRepositoryRO<'a> {
818    pub fn new(redb_table: Box<dyn DocumentTableRO + 'a>) -> Self {
819        DocumentRepositoryRO { redb_table }
820    }
821    pub fn get(&self, id: &EntityId) -> Result<Option<Document>, RepositoryError> {
822        self.redb_table.get(id)
823    }
824    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Document>>, RepositoryError> {
825        self.redb_table.get_multi(ids)
826    }
827    pub fn get_all(&self) -> Result<Vec<Document>, RepositoryError> {
828        self.redb_table.get_all()
829    }
830    pub fn get_relationship(
831        &self,
832        id: &EntityId,
833        field: &DocumentRelationshipField,
834    ) -> Result<Vec<EntityId>, RepositoryError> {
835        self.redb_table.get_relationship(id, field)
836    }
837    pub fn get_relationship_many(
838        &self,
839        ids: &[EntityId],
840        field: &DocumentRelationshipField,
841    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
842        self.redb_table.get_relationship_many(ids, field)
843    }
844    pub fn get_relationship_count(
845        &self,
846        id: &EntityId,
847        field: &DocumentRelationshipField,
848    ) -> Result<usize, RepositoryError> {
849        self.redb_table.get_relationship_count(id, field)
850    }
851    pub fn get_relationship_in_range(
852        &self,
853        id: &EntityId,
854        field: &DocumentRelationshipField,
855        offset: usize,
856        limit: usize,
857    ) -> Result<Vec<EntityId>, RepositoryError> {
858        self.redb_table
859            .get_relationship_in_range(id, field, offset, limit)
860    }
861    pub fn get_relationships_from_right_ids(
862        &self,
863        field: &DocumentRelationshipField,
864        right_ids: &[EntityId],
865    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
866        self.redb_table
867            .get_relationships_from_right_ids(field, right_ids)
868    }
869}