Skip to main content

text_document_common/direct_access/document/
document_repository.rs

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