Skip to main content

text_document_common/direct_access/document/
document_table.rs

1use crate::database::hashmap_store::{
2    HashMapStore, delete_from_backward_junction, junction_get, junction_remove, junction_set,
3};
4use crate::entities::*;
5use crate::error::RepositoryError;
6use crate::types::EntityId;
7use crate::{impl_relationship_methods, impl_write_relationship_methods};
8use std::collections::HashMap;
9use std::sync::RwLock;
10
11use super::document_repository::{DocumentRelationshipField, DocumentTable, DocumentTableRO};
12
13pub struct DocumentHashMapTable<'a> {
14    store: &'a HashMapStore,
15}
16
17impl<'a> DocumentHashMapTable<'a> {
18    pub fn new(store: &'a HashMapStore) -> Self {
19        Self { store }
20    }
21
22    fn resolve_junction(
23        &self,
24        field: &DocumentRelationshipField,
25    ) -> &RwLock<HashMap<EntityId, Vec<EntityId>>> {
26        match field {
27            DocumentRelationshipField::Frames => &self.store.jn_frame_from_document_frames,
28            DocumentRelationshipField::Lists => &self.store.jn_list_from_document_lists,
29            DocumentRelationshipField::Resources => &self.store.jn_resource_from_document_resources,
30            DocumentRelationshipField::Tables => &self.store.jn_table_from_document_tables,
31        }
32    }
33
34    fn hydrate(&self, entity: &mut Document) {
35        entity.frames = junction_get(&self.store.jn_frame_from_document_frames, &entity.id);
36        entity.lists = junction_get(&self.store.jn_list_from_document_lists, &entity.id);
37        entity.resources =
38            junction_get(&self.store.jn_resource_from_document_resources, &entity.id);
39        entity.tables = junction_get(&self.store.jn_table_from_document_tables, &entity.id);
40    }
41}
42
43impl<'a> DocumentTable for DocumentHashMapTable<'a> {
44    fn create(&mut self, entity: &Document) -> Result<Document, RepositoryError> {
45        self.create_multi(std::slice::from_ref(entity))
46            .map(|v| v.into_iter().next().unwrap())
47    }
48
49    fn create_multi(&mut self, entities: &[Document]) -> Result<Vec<Document>, RepositoryError> {
50        let mut created = Vec::with_capacity(entities.len());
51        let mut docs = self.store.documents.write().unwrap();
52
53        for entity in entities {
54            let new_entity = if entity.id == EntityId::default() {
55                let id = self.store.next_id("document");
56                Document {
57                    id,
58                    ..entity.clone()
59                }
60            } else {
61                if docs.contains_key(&entity.id) {
62                    return Err(RepositoryError::DuplicateId {
63                        entity: "Document",
64                        id: entity.id,
65                    });
66                }
67                entity.clone()
68            };
69
70            docs.insert(new_entity.id, new_entity.clone());
71            junction_set(
72                &self.store.jn_frame_from_document_frames,
73                new_entity.id,
74                new_entity.frames.clone(),
75            );
76            junction_set(
77                &self.store.jn_list_from_document_lists,
78                new_entity.id,
79                new_entity.lists.clone(),
80            );
81            junction_set(
82                &self.store.jn_resource_from_document_resources,
83                new_entity.id,
84                new_entity.resources.clone(),
85            );
86            junction_set(
87                &self.store.jn_table_from_document_tables,
88                new_entity.id,
89                new_entity.tables.clone(),
90            );
91            created.push(new_entity);
92        }
93        Ok(created)
94    }
95
96    fn get(&self, id: &EntityId) -> Result<Option<Document>, RepositoryError> {
97        let docs = self.store.documents.read().unwrap();
98        match docs.get(id) {
99            Some(entity) => {
100                let mut e = entity.clone();
101                drop(docs);
102                self.hydrate(&mut e);
103                Ok(Some(e))
104            }
105            None => Ok(None),
106        }
107    }
108
109    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Document>>, RepositoryError> {
110        let mut result = Vec::with_capacity(ids.len());
111        for id in ids {
112            result.push(self.get(id)?);
113        }
114        Ok(result)
115    }
116
117    fn get_all(&self) -> Result<Vec<Document>, RepositoryError> {
118        let docs = self.store.documents.read().unwrap();
119        let entries: Vec<Document> = docs.values().cloned().collect();
120        drop(docs);
121        let mut result = Vec::with_capacity(entries.len());
122        for mut entity in entries {
123            self.hydrate(&mut entity);
124            result.push(entity);
125        }
126        Ok(result)
127    }
128
129    fn update(&mut self, entity: &Document) -> Result<Document, RepositoryError> {
130        self.update_multi(std::slice::from_ref(entity))
131            .map(|v| v.into_iter().next().unwrap())
132    }
133
134    fn update_multi(&mut self, entities: &[Document]) -> Result<Vec<Document>, RepositoryError> {
135        let mut docs = self.store.documents.write().unwrap();
136        for entity in entities {
137            docs.insert(entity.id, entity.clone());
138        }
139        drop(docs);
140        let ids: Vec<EntityId> = entities.iter().map(|e| e.id).collect();
141        let result = self.get_multi(&ids)?;
142        Ok(result.into_iter().flatten().collect())
143    }
144
145    fn update_with_relationships(
146        &mut self,
147        entity: &Document,
148    ) -> Result<Document, RepositoryError> {
149        self.update_with_relationships_multi(std::slice::from_ref(entity))
150            .map(|v| v.into_iter().next().unwrap())
151    }
152
153    fn update_with_relationships_multi(
154        &mut self,
155        entities: &[Document],
156    ) -> Result<Vec<Document>, RepositoryError> {
157        let mut docs = self.store.documents.write().unwrap();
158        for entity in entities {
159            docs.insert(entity.id, entity.clone());
160            junction_set(
161                &self.store.jn_frame_from_document_frames,
162                entity.id,
163                entity.frames.clone(),
164            );
165            junction_set(
166                &self.store.jn_list_from_document_lists,
167                entity.id,
168                entity.lists.clone(),
169            );
170            junction_set(
171                &self.store.jn_resource_from_document_resources,
172                entity.id,
173                entity.resources.clone(),
174            );
175            junction_set(
176                &self.store.jn_table_from_document_tables,
177                entity.id,
178                entity.tables.clone(),
179            );
180        }
181        drop(docs);
182        let ids: Vec<EntityId> = entities.iter().map(|e| e.id).collect();
183        let result = self.get_multi(&ids)?;
184        Ok(result.into_iter().flatten().collect())
185    }
186
187    fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError> {
188        self.remove_multi(std::slice::from_ref(id))
189    }
190
191    fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError> {
192        let mut docs = self.store.documents.write().unwrap();
193        for id in ids {
194            docs.remove(id);
195            junction_remove(&self.store.jn_frame_from_document_frames, id);
196            junction_remove(&self.store.jn_list_from_document_lists, id);
197            junction_remove(&self.store.jn_resource_from_document_resources, id);
198            junction_remove(&self.store.jn_table_from_document_tables, id);
199            delete_from_backward_junction(&self.store.jn_document_from_root_document, id);
200        }
201        Ok(())
202    }
203
204    impl_write_relationship_methods!(DocumentHashMapTable<'a>, DocumentRelationshipField);
205}
206
207pub struct DocumentHashMapTableRO<'a> {
208    store: &'a HashMapStore,
209}
210
211impl<'a> DocumentHashMapTableRO<'a> {
212    pub fn new(store: &'a HashMapStore) -> Self {
213        Self { store }
214    }
215
216    fn resolve_junction(
217        &self,
218        field: &DocumentRelationshipField,
219    ) -> &RwLock<HashMap<EntityId, Vec<EntityId>>> {
220        match field {
221            DocumentRelationshipField::Frames => &self.store.jn_frame_from_document_frames,
222            DocumentRelationshipField::Lists => &self.store.jn_list_from_document_lists,
223            DocumentRelationshipField::Resources => &self.store.jn_resource_from_document_resources,
224            DocumentRelationshipField::Tables => &self.store.jn_table_from_document_tables,
225        }
226    }
227
228    fn hydrate(&self, entity: &mut Document) {
229        entity.frames = junction_get(&self.store.jn_frame_from_document_frames, &entity.id);
230        entity.lists = junction_get(&self.store.jn_list_from_document_lists, &entity.id);
231        entity.resources =
232            junction_get(&self.store.jn_resource_from_document_resources, &entity.id);
233        entity.tables = junction_get(&self.store.jn_table_from_document_tables, &entity.id);
234    }
235}
236
237impl<'a> DocumentTableRO for DocumentHashMapTableRO<'a> {
238    fn get(&self, id: &EntityId) -> Result<Option<Document>, RepositoryError> {
239        let docs = self.store.documents.read().unwrap();
240        match docs.get(id) {
241            Some(entity) => {
242                let mut e = entity.clone();
243                drop(docs);
244                self.hydrate(&mut e);
245                Ok(Some(e))
246            }
247            None => Ok(None),
248        }
249    }
250
251    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Document>>, RepositoryError> {
252        let mut result = Vec::with_capacity(ids.len());
253        for id in ids {
254            result.push(self.get(id)?);
255        }
256        Ok(result)
257    }
258
259    fn get_all(&self) -> Result<Vec<Document>, RepositoryError> {
260        let docs = self.store.documents.read().unwrap();
261        let entries: Vec<Document> = docs.values().cloned().collect();
262        drop(docs);
263        let mut result = Vec::with_capacity(entries.len());
264        for mut entity in entries {
265            self.hydrate(&mut entity);
266            result.push(entity);
267        }
268        Ok(result)
269    }
270
271    impl_relationship_methods!(DocumentHashMapTableRO<'a>, DocumentRelationshipField);
272}