Skip to main content

common/direct_access/resource/
resource_repository.rs

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