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