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