Skip to main content

text_document_common/direct_access/resource/
resource_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::Resource,
9    event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10    snapshot::EntityTreeSnapshot,
11    types::EntityId,
12};
13
14use crate::direct_access::document::DocumentRelationshipField;
15use crate::error::RepositoryError;
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum ResourceRelationshipField {}
20
21impl Display for ResourceRelationshipField {
22    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23        write!(f, "{:?}", self)
24    }
25}
26
27pub trait ResourceTable {
28    fn create(&mut self, entity: &Resource) -> Result<Resource, RepositoryError>;
29    fn create_multi(&mut self, entities: &[Resource]) -> Result<Vec<Resource>, RepositoryError>;
30    fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError>;
31    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError>;
32    fn get_all(&self) -> Result<Vec<Resource>, RepositoryError>;
33    fn update(&mut self, entity: &Resource) -> Result<Resource, RepositoryError>;
34    fn update_multi(&mut self, entities: &[Resource]) -> Result<Vec<Resource>, RepositoryError>;
35    fn update_with_relationships(&mut self, entity: &Resource)
36    -> Result<Resource, RepositoryError>;
37    fn update_with_relationships_multi(
38        &mut self,
39        entities: &[Resource],
40    ) -> Result<Vec<Resource>, RepositoryError>;
41    fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
42    fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
43}
44
45pub trait ResourceTableRO {
46    fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError>;
47    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError>;
48    fn get_all(&self) -> Result<Vec<Resource>, RepositoryError>;
49}
50
51pub struct ResourceRepository<'a> {
52    redb_table: Box<dyn ResourceTable + 'a>,
53    transaction: &'a Transaction,
54}
55
56impl<'a> ResourceRepository<'a> {
57    pub fn new(redb_table: Box<dyn ResourceTable + 'a>, transaction: &'a Transaction) -> Self {
58        ResourceRepository {
59            redb_table,
60            transaction,
61        }
62    }
63
64    pub fn create_orphan(
65        &mut self,
66        event_buffer: &mut EventBuffer,
67        entity: &Resource,
68    ) -> Result<Resource, RepositoryError> {
69        let new = self.redb_table.create(entity)?;
70        event_buffer.push(Event {
71            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
72            ids: vec![new.id],
73            data: None,
74        });
75        Ok(new)
76    }
77
78    pub fn create_orphan_multi(
79        &mut self,
80        event_buffer: &mut EventBuffer,
81        entities: &[Resource],
82    ) -> Result<Vec<Resource>, RepositoryError> {
83        let new_entities = self.redb_table.create_multi(entities)?;
84        event_buffer.push(Event {
85            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
86            ids: new_entities.iter().map(|e| e.id).collect(),
87            data: None,
88        });
89        Ok(new_entities)
90    }
91    pub fn create(
92        &mut self,
93        event_buffer: &mut EventBuffer,
94        entity: &Resource,
95        owner_id: EntityId,
96        index: i32,
97    ) -> Result<Resource, RepositoryError> {
98        let new = self.redb_table.create(entity)?;
99        let created_id = new.id;
100
101        let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
102        // Insert at index
103        if index >= 0 && (index as usize) < relationship_ids.len() {
104            relationship_ids.insert(index as usize, created_id);
105        } else {
106            relationship_ids.push(created_id);
107        }
108
109        self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
110        event_buffer.push(Event {
111            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
112            ids: vec![created_id],
113            data: None,
114        });
115        Ok(new)
116    }
117
118    pub fn create_multi(
119        &mut self,
120        event_buffer: &mut EventBuffer,
121        entities: &[Resource],
122        owner_id: EntityId,
123        index: i32,
124    ) -> Result<Vec<Resource>, RepositoryError> {
125        let new_entities = self.redb_table.create_multi(entities)?;
126        let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
127
128        let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
129        if index >= 0 && (index as usize) < relationship_ids.len() {
130            for (i, id) in created_ids.iter().enumerate() {
131                relationship_ids.insert(index as usize + i, *id);
132            }
133        } else {
134            relationship_ids.extend(created_ids.iter());
135        }
136
137        self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
138        event_buffer.push(Event {
139            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
140            ids: created_ids,
141            data: None,
142        });
143        Ok(new_entities)
144    }
145
146    pub fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError> {
147        self.redb_table.get(id)
148    }
149    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError> {
150        self.redb_table.get_multi(ids)
151    }
152    pub fn get_all(&self) -> Result<Vec<Resource>, RepositoryError> {
153        self.redb_table.get_all()
154    }
155
156    pub fn update(
157        &mut self,
158        event_buffer: &mut EventBuffer,
159        entity: &Resource,
160    ) -> Result<Resource, RepositoryError> {
161        let updated = self.redb_table.update(entity)?;
162        event_buffer.push(Event {
163            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
164            ids: vec![updated.id],
165            data: None,
166        });
167        Ok(updated)
168    }
169
170    pub fn update_multi(
171        &mut self,
172        event_buffer: &mut EventBuffer,
173        entities: &[Resource],
174    ) -> Result<Vec<Resource>, RepositoryError> {
175        let updated = self.redb_table.update_multi(entities)?;
176        event_buffer.push(Event {
177            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
178            ids: updated.iter().map(|e| e.id).collect(),
179            data: None,
180        });
181        Ok(updated)
182    }
183
184    pub fn update_with_relationships(
185        &mut self,
186        event_buffer: &mut EventBuffer,
187        entity: &Resource,
188    ) -> Result<Resource, RepositoryError> {
189        let updated = self.redb_table.update_with_relationships(entity)?;
190        event_buffer.push(Event {
191            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
192            ids: vec![updated.id],
193            data: None,
194        });
195        Ok(updated)
196    }
197
198    pub fn update_with_relationships_multi(
199        &mut self,
200        event_buffer: &mut EventBuffer,
201        entities: &[Resource],
202    ) -> Result<Vec<Resource>, RepositoryError> {
203        let updated = self.redb_table.update_with_relationships_multi(entities)?;
204        event_buffer.push(Event {
205            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
206            ids: updated.iter().map(|e| e.id).collect(),
207            data: None,
208        });
209        Ok(updated)
210    }
211
212    pub fn remove(
213        &mut self,
214        event_buffer: &mut EventBuffer,
215        id: &EntityId,
216    ) -> Result<(), RepositoryError> {
217        let _entity = match self.redb_table.get(id)? {
218            Some(e) => e,
219            None => return Ok(()),
220        };
221        // get all strong forward relationship fields
222
223        // remove all strong relationships, initiating a cascade remove
224
225        // Before removal, find which owner(s) reference this entity
226        let affected_owner_ids: Vec<EntityId> = {
227            let owner_repo =
228                repository_factory::write::create_document_repository(self.transaction);
229            owner_repo
230                .get_relationships_from_right_ids(&DocumentRelationshipField::Resources, &[*id])?
231                .into_iter()
232                .map(|(owner_id, _)| owner_id)
233                .collect()
234        };
235        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
236        let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
237            std::collections::HashMap::new();
238        for owner_id in &affected_owner_ids {
239            owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
240        }
241
242        // remove entity
243        self.redb_table.remove(id)?;
244        event_buffer.push(Event {
245            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Removed)),
246            ids: vec![*id],
247            data: None,
248        });
249        // Update each affected owner's relationship to exclude removed ID (emits Updated event)
250        for owner_id in &affected_owner_ids {
251            if let Some(rel_ids) = owner_rel_before.get(owner_id) {
252                let updated: Vec<EntityId> =
253                    rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
254                self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
255            }
256        }
257
258        Ok(())
259    }
260
261    pub fn remove_multi(
262        &mut self,
263        event_buffer: &mut EventBuffer,
264        ids: &[EntityId],
265    ) -> Result<(), RepositoryError> {
266        let entities = self.redb_table.get_multi(ids)?;
267        if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
268            return Ok(());
269        }
270
271        // get all strong forward relationship fields
272
273        // remove all strong relationships, initiating a cascade remove
274
275        // Before removal, find which owner(s) reference these entities
276        let affected_owner_ids: Vec<EntityId> = {
277            let owner_repo =
278                repository_factory::write::create_document_repository(self.transaction);
279            owner_repo
280                .get_relationships_from_right_ids(&DocumentRelationshipField::Resources, ids)?
281                .into_iter()
282                .map(|(owner_id, _)| owner_id)
283                .collect()
284        };
285        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
286        let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
287            std::collections::HashMap::new();
288        for owner_id in &affected_owner_ids {
289            owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
290        }
291
292        self.redb_table.remove_multi(ids)?;
293        event_buffer.push(Event {
294            origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Removed)),
295            ids: ids.into(),
296            data: None,
297        });
298        // Update each affected owner's relationship to exclude removed IDs (emits Updated event)
299        {
300            let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
301            for owner_id in &affected_owner_ids {
302                if let Some(rel_ids) = owner_rel_before.get(owner_id) {
303                    let updated: Vec<EntityId> = rel_ids
304                        .iter()
305                        .copied()
306                        .filter(|rid| !removed_set.contains(rid))
307                        .collect();
308                    self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
309                }
310            }
311        }
312
313        Ok(())
314    }
315    pub fn get_relationships_from_owner(
316        &self,
317        owner_id: &EntityId,
318    ) -> Result<Vec<EntityId>, RepositoryError> {
319        let repo = repository_factory::write::create_document_repository(self.transaction);
320        repo.get_relationship(owner_id, &DocumentRelationshipField::Resources)
321    }
322
323    pub fn set_relationships_in_owner(
324        &mut self,
325        event_buffer: &mut EventBuffer,
326        owner_id: &EntityId,
327        ids: &[EntityId],
328    ) -> Result<(), RepositoryError> {
329        let mut repo = repository_factory::write::create_document_repository(self.transaction);
330        repo.set_relationship(
331            event_buffer,
332            owner_id,
333            &DocumentRelationshipField::Resources,
334            ids,
335        )
336    }
337
338    pub fn snapshot(&self, _ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
339        let store_snap = self.transaction.snapshot_store();
340        Ok(EntityTreeSnapshot {
341            store_snapshot: Some(store_snap),
342        })
343    }
344
345    pub fn restore(
346        &mut self,
347        event_buffer: &mut EventBuffer,
348        snap: &EntityTreeSnapshot,
349    ) -> Result<(), RepositoryError> {
350        let store_snap = snap
351            .store_snapshot
352            .as_ref()
353            .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
354        self.transaction.restore_store(store_snap);
355
356        let store = self.transaction.get_store();
357
358        // Resource: Created only (leaf, no strong children)
359        let res_ids: Vec<_> = store.resources.read().unwrap().keys().copied().collect();
360        if !res_ids.is_empty() {
361            event_buffer.push(Event {
362                origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
363                ids: res_ids,
364                data: None,
365            });
366        }
367
368        Ok(())
369    }
370}
371
372pub struct ResourceRepositoryRO<'a> {
373    redb_table: Box<dyn ResourceTableRO + 'a>,
374}
375impl<'a> ResourceRepositoryRO<'a> {
376    pub fn new(redb_table: Box<dyn ResourceTableRO + 'a>) -> Self {
377        ResourceRepositoryRO { redb_table }
378    }
379    pub fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError> {
380        self.redb_table.get(id)
381    }
382    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError> {
383        self.redb_table.get_multi(ids)
384    }
385    pub fn get_all(&self) -> Result<Vec<Resource>, RepositoryError> {
386        self.redb_table.get_all()
387    }
388}