Skip to main content

text_document_common/direct_access/root/
root_table.rs

1use crate::database::hashmap_store::{
2    HashMapStore, junction_get, junction_get_relationships_from_right_ids, junction_move_ids,
3    junction_remove, junction_set,
4};
5use crate::entities::*;
6use crate::error::RepositoryError;
7use crate::types::EntityId;
8use std::collections::HashMap;
9use std::sync::RwLock;
10
11use super::root_repository::{RootRelationshipField, RootTable, RootTableRO};
12
13pub struct RootHashMapTable<'a> {
14    store: &'a HashMapStore,
15}
16
17impl<'a> RootHashMapTable<'a> {
18    pub fn new(store: &'a HashMapStore) -> Self {
19        Self { store }
20    }
21
22    fn resolve_junction(
23        &self,
24        field: &RootRelationshipField,
25    ) -> &RwLock<HashMap<EntityId, Vec<EntityId>>> {
26        match field {
27            RootRelationshipField::Document => &self.store.jn_document_from_root_document,
28        }
29    }
30
31    fn hydrate(&self, entity: &mut Root) -> bool {
32        match junction_get(&self.store.jn_document_from_root_document, &entity.id)
33            .into_iter()
34            .next()
35        {
36            Some(val) => {
37                entity.document = val;
38                true
39            }
40            None => {
41                log::warn!(
42                    "Root {} has incomplete junction data (missing document), treating as not found",
43                    entity.id
44                );
45                false
46            }
47        }
48    }
49}
50
51impl<'a> RootTable for RootHashMapTable<'a> {
52    fn create(&mut self, entity: &Root) -> Result<Root, RepositoryError> {
53        self.create_multi(std::slice::from_ref(entity))
54            .map(|v| v.into_iter().next().unwrap())
55    }
56
57    fn create_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError> {
58        let mut created = Vec::with_capacity(entities.len());
59        let mut roots = self.store.roots.write().unwrap();
60
61        for entity in entities {
62            let new_entity = if entity.id == EntityId::default() {
63                let id = self.store.next_id("root");
64                Root {
65                    id,
66                    ..entity.clone()
67                }
68            } else {
69                if roots.contains_key(&entity.id) {
70                    return Err(RepositoryError::DuplicateId {
71                        entity: "Root",
72                        id: entity.id,
73                    });
74                }
75                entity.clone()
76            };
77
78            // one-to-one constraint check
79            {
80                let jn = self.store.jn_document_from_root_document.read().unwrap();
81                for (existing_id, right_ids) in jn.iter() {
82                    if *existing_id != new_entity.id && right_ids.contains(&new_entity.document) {
83                        panic!(
84                            "One-to-one constraint violation: Document {} is already referenced by Root {}",
85                            new_entity.document, existing_id
86                        );
87                    }
88                }
89            }
90
91            roots.insert(new_entity.id, new_entity.clone());
92            junction_set(
93                &self.store.jn_document_from_root_document,
94                new_entity.id,
95                vec![new_entity.document],
96            );
97            created.push(new_entity);
98        }
99        Ok(created)
100    }
101
102    fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
103        let entity = {
104            let roots = self.store.roots.read().unwrap();
105            roots.get(id).cloned()
106        };
107        match entity {
108            Some(mut e) => {
109                let complete = self.hydrate(&mut e);
110                Ok(if complete { Some(e) } else { None })
111            }
112            None => Ok(None),
113        }
114    }
115
116    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
117        let mut result = Vec::with_capacity(ids.len());
118        for id in ids {
119            result.push(self.get(id)?);
120        }
121        Ok(result)
122    }
123
124    fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
125        let roots = self.store.roots.read().unwrap();
126        let entries: Vec<Root> = roots.values().cloned().collect();
127        drop(roots);
128        let mut result = Vec::with_capacity(entries.len());
129        for mut entity in entries {
130            if self.hydrate(&mut entity) {
131                result.push(entity);
132            }
133        }
134        Ok(result)
135    }
136
137    fn update(&mut self, entity: &Root) -> Result<Root, RepositoryError> {
138        self.update_multi(std::slice::from_ref(entity))
139            .map(|v| v.into_iter().next().unwrap())
140    }
141
142    fn update_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError> {
143        let mut roots = self.store.roots.write().unwrap();
144        for entity in entities {
145            roots.insert(entity.id, entity.clone());
146        }
147        drop(roots);
148        let ids: Vec<EntityId> = entities.iter().map(|e| e.id).collect();
149        let result = self.get_multi(&ids)?;
150        Ok(result.into_iter().flatten().collect())
151    }
152
153    fn update_with_relationships(&mut self, entity: &Root) -> Result<Root, RepositoryError> {
154        self.update_with_relationships_multi(std::slice::from_ref(entity))
155            .map(|v| v.into_iter().next().unwrap())
156    }
157
158    fn update_with_relationships_multi(
159        &mut self,
160        entities: &[Root],
161    ) -> Result<Vec<Root>, RepositoryError> {
162        let mut roots = self.store.roots.write().unwrap();
163        for entity in entities {
164            // one-to-one constraint check
165            {
166                let jn = self.store.jn_document_from_root_document.read().unwrap();
167                for (existing_id, right_ids) in jn.iter() {
168                    if *existing_id != entity.id && right_ids.contains(&entity.document) {
169                        panic!(
170                            "One-to-one constraint violation: Document {} is already referenced by Root {}",
171                            entity.document, existing_id
172                        );
173                    }
174                }
175            }
176            roots.insert(entity.id, entity.clone());
177            junction_set(
178                &self.store.jn_document_from_root_document,
179                entity.id,
180                vec![entity.document],
181            );
182        }
183        drop(roots);
184        let ids: Vec<EntityId> = entities.iter().map(|e| e.id).collect();
185        let result = self.get_multi(&ids)?;
186        Ok(result.into_iter().flatten().collect())
187    }
188
189    fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError> {
190        self.remove_multi(std::slice::from_ref(id))
191    }
192
193    fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError> {
194        let mut roots = self.store.roots.write().unwrap();
195        for id in ids {
196            roots.remove(id);
197            junction_remove(&self.store.jn_document_from_root_document, id);
198        }
199        Ok(())
200    }
201
202    fn get_relationship(
203        &self,
204        id: &EntityId,
205        field: &RootRelationshipField,
206    ) -> Result<Vec<EntityId>, RepositoryError> {
207        Ok(junction_get(self.resolve_junction(field), id))
208    }
209
210    fn get_relationship_many(
211        &self,
212        ids: &[EntityId],
213        field: &RootRelationshipField,
214    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
215        let jn = self.resolve_junction(field);
216        let mut map = std::collections::HashMap::new();
217        for id in ids {
218            map.insert(*id, junction_get(jn, id));
219        }
220        Ok(map)
221    }
222
223    fn get_relationship_count(
224        &self,
225        id: &EntityId,
226        field: &RootRelationshipField,
227    ) -> Result<usize, RepositoryError> {
228        Ok(junction_get(self.resolve_junction(field), id).len())
229    }
230
231    fn get_relationship_in_range(
232        &self,
233        id: &EntityId,
234        field: &RootRelationshipField,
235        offset: usize,
236        limit: usize,
237    ) -> Result<Vec<EntityId>, RepositoryError> {
238        let all = junction_get(self.resolve_junction(field), id);
239        Ok(all.into_iter().skip(offset).take(limit).collect())
240    }
241
242    fn get_relationships_from_right_ids(
243        &self,
244        field: &RootRelationshipField,
245        right_ids: &[EntityId],
246    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
247        Ok(junction_get_relationships_from_right_ids(
248            self.resolve_junction(field),
249            right_ids,
250        ))
251    }
252
253    fn set_relationship_multi(
254        &mut self,
255        field: &RootRelationshipField,
256        relationships: Vec<(EntityId, Vec<EntityId>)>,
257    ) -> Result<(), RepositoryError> {
258        let jn = self.resolve_junction(field);
259        for (left_id, entities) in relationships {
260            junction_set(jn, left_id, entities);
261        }
262        Ok(())
263    }
264
265    fn set_relationship(
266        &mut self,
267        id: &EntityId,
268        field: &RootRelationshipField,
269        right_ids: &[EntityId],
270    ) -> Result<(), RepositoryError> {
271        junction_set(self.resolve_junction(field), *id, right_ids.to_vec());
272        Ok(())
273    }
274
275    fn move_relationship_ids(
276        &mut self,
277        id: &EntityId,
278        field: &RootRelationshipField,
279        ids_to_move: &[EntityId],
280        new_index: i32,
281    ) -> Result<Vec<EntityId>, RepositoryError> {
282        Ok(junction_move_ids(
283            self.resolve_junction(field),
284            id,
285            ids_to_move,
286            new_index,
287        ))
288    }
289}
290
291pub struct RootHashMapTableRO<'a> {
292    store: &'a HashMapStore,
293}
294
295impl<'a> RootHashMapTableRO<'a> {
296    pub fn new(store: &'a HashMapStore) -> Self {
297        Self { store }
298    }
299
300    fn resolve_junction(
301        &self,
302        field: &RootRelationshipField,
303    ) -> &RwLock<HashMap<EntityId, Vec<EntityId>>> {
304        match field {
305            RootRelationshipField::Document => &self.store.jn_document_from_root_document,
306        }
307    }
308
309    fn hydrate(&self, entity: &mut Root) -> bool {
310        match junction_get(&self.store.jn_document_from_root_document, &entity.id)
311            .into_iter()
312            .next()
313        {
314            Some(val) => {
315                entity.document = val;
316                true
317            }
318            None => {
319                log::warn!(
320                    "Root {} has incomplete junction data (missing document), treating as not found",
321                    entity.id
322                );
323                false
324            }
325        }
326    }
327}
328
329impl<'a> RootTableRO for RootHashMapTableRO<'a> {
330    fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
331        let roots = self.store.roots.read().unwrap();
332        match roots.get(id) {
333            Some(entity) => {
334                let mut e = entity.clone();
335                drop(roots);
336                let complete = self.hydrate(&mut e);
337                Ok(if complete { Some(e) } else { None })
338            }
339            None => Ok(None),
340        }
341    }
342
343    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
344        if ids.is_empty() {
345            return Ok(Vec::new());
346        }
347        let mut result = Vec::with_capacity(ids.len());
348        for id in ids {
349            result.push(self.get(id)?);
350        }
351        Ok(result)
352    }
353
354    fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
355        let roots = self.store.roots.read().unwrap();
356        let entries: Vec<Root> = roots.values().cloned().collect();
357        drop(roots);
358        let mut result = Vec::with_capacity(entries.len());
359        for mut entity in entries {
360            if self.hydrate(&mut entity) {
361                result.push(entity);
362            }
363        }
364        Ok(result)
365    }
366
367    fn get_relationship(
368        &self,
369        id: &EntityId,
370        field: &RootRelationshipField,
371    ) -> Result<Vec<EntityId>, RepositoryError> {
372        Ok(junction_get(self.resolve_junction(field), id))
373    }
374
375    fn get_relationship_many(
376        &self,
377        ids: &[EntityId],
378        field: &RootRelationshipField,
379    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
380        let jn = self.resolve_junction(field);
381        let mut map = std::collections::HashMap::new();
382        for id in ids {
383            map.insert(*id, junction_get(jn, id));
384        }
385        Ok(map)
386    }
387
388    fn get_relationship_count(
389        &self,
390        id: &EntityId,
391        field: &RootRelationshipField,
392    ) -> Result<usize, RepositoryError> {
393        Ok(junction_get(self.resolve_junction(field), id).len())
394    }
395
396    fn get_relationship_in_range(
397        &self,
398        id: &EntityId,
399        field: &RootRelationshipField,
400        offset: usize,
401        limit: usize,
402    ) -> Result<Vec<EntityId>, RepositoryError> {
403        let all = junction_get(self.resolve_junction(field), id);
404        Ok(all.into_iter().skip(offset).take(limit).collect())
405    }
406
407    fn get_relationships_from_right_ids(
408        &self,
409        field: &RootRelationshipField,
410        right_ids: &[EntityId],
411    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
412        Ok(junction_get_relationships_from_right_ids(
413            self.resolve_junction(field),
414            right_ids,
415        ))
416    }
417}