1use 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 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 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 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 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 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 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 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 {
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 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 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}