text_document_common/direct_access/root/
root_table.rs1use 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 {
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 {
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}