1use crate::entities::*;
11use crate::snapshot::{StoreSnapshot, StoreSnapshotTrait};
12use crate::types::EntityId;
13use im::HashMap;
14use std::sync::RwLock;
15
16#[derive(Debug, Default)]
21pub struct HashMapStore {
22 pub roots: RwLock<HashMap<EntityId, Root>>,
24 pub workspaces: RwLock<HashMap<EntityId, Workspace>>,
25 pub systems: RwLock<HashMap<EntityId, System>>,
26 pub entitys: RwLock<HashMap<EntityId, Entity>>,
27 pub fields: RwLock<HashMap<EntityId, Field>>,
28 pub features: RwLock<HashMap<EntityId, Feature>>,
29 pub files: RwLock<HashMap<EntityId, File>>,
30 pub use_cases: RwLock<HashMap<EntityId, UseCase>>,
31 pub dtos: RwLock<HashMap<EntityId, Dto>>,
32 pub dto_fields: RwLock<HashMap<EntityId, DtoField>>,
33 pub globals: RwLock<HashMap<EntityId, Global>>,
34 pub relationships: RwLock<HashMap<EntityId, Relationship>>,
35 pub user_interfaces: RwLock<HashMap<EntityId, UserInterface>>,
36
37 pub jn_system_from_root_system: RwLock<HashMap<EntityId, Vec<EntityId>>>,
39 pub jn_workspace_from_root_workspace: RwLock<HashMap<EntityId, Vec<EntityId>>>,
40 pub jn_entity_from_workspace_entities: RwLock<HashMap<EntityId, Vec<EntityId>>>,
41 pub jn_feature_from_workspace_features: RwLock<HashMap<EntityId, Vec<EntityId>>>,
42 pub jn_global_from_workspace_global: RwLock<HashMap<EntityId, Vec<EntityId>>>,
43 pub jn_user_interface_from_workspace_user_interface: RwLock<HashMap<EntityId, Vec<EntityId>>>,
44 pub jn_file_from_system_files: RwLock<HashMap<EntityId, Vec<EntityId>>>,
45 pub jn_field_from_entity_fields: RwLock<HashMap<EntityId, Vec<EntityId>>>,
46 pub jn_entity_from_entity_inherits_from: RwLock<HashMap<EntityId, Vec<EntityId>>>,
47 pub jn_relationship_from_entity_relationships: RwLock<HashMap<EntityId, Vec<EntityId>>>,
48 pub jn_entity_from_field_entity: RwLock<HashMap<EntityId, Vec<EntityId>>>,
49 pub jn_use_case_from_feature_use_cases: RwLock<HashMap<EntityId, Vec<EntityId>>>,
50 pub jn_entity_from_file_entity: RwLock<HashMap<EntityId, Vec<EntityId>>>,
51 pub jn_feature_from_file_feature: RwLock<HashMap<EntityId, Vec<EntityId>>>,
52 pub jn_field_from_file_field: RwLock<HashMap<EntityId, Vec<EntityId>>>,
53 pub jn_use_case_from_file_use_case: RwLock<HashMap<EntityId, Vec<EntityId>>>,
54 pub jn_dto_from_use_case_dto_in: RwLock<HashMap<EntityId, Vec<EntityId>>>,
55 pub jn_dto_from_use_case_dto_out: RwLock<HashMap<EntityId, Vec<EntityId>>>,
56 pub jn_entity_from_use_case_entities: RwLock<HashMap<EntityId, Vec<EntityId>>>,
57 pub jn_dto_field_from_dto_fields: RwLock<HashMap<EntityId, Vec<EntityId>>>,
58 pub jn_entity_from_relationship_left_entity: RwLock<HashMap<EntityId, Vec<EntityId>>>,
59 pub jn_entity_from_relationship_right_entity: RwLock<HashMap<EntityId, Vec<EntityId>>>,
60
61 pub counters: RwLock<std::collections::HashMap<String, EntityId>>,
63
64 savepoints: RwLock<std::collections::HashMap<u64, HashMapStoreSnapshot>>,
66 next_savepoint_id: RwLock<u64>,
67}
68
69impl HashMapStore {
70 pub fn new() -> Self {
71 Self::default()
72 }
73
74 pub fn snapshot(&self) -> HashMapStoreSnapshot {
76 HashMapStoreSnapshot {
77 roots: self.roots.read().unwrap().clone(),
78 workspaces: self.workspaces.read().unwrap().clone(),
79 systems: self.systems.read().unwrap().clone(),
80 entitys: self.entitys.read().unwrap().clone(),
81 fields: self.fields.read().unwrap().clone(),
82 features: self.features.read().unwrap().clone(),
83 files: self.files.read().unwrap().clone(),
84 use_cases: self.use_cases.read().unwrap().clone(),
85 dtos: self.dtos.read().unwrap().clone(),
86 dto_fields: self.dto_fields.read().unwrap().clone(),
87 globals: self.globals.read().unwrap().clone(),
88 relationships: self.relationships.read().unwrap().clone(),
89 user_interfaces: self.user_interfaces.read().unwrap().clone(),
90 jn_system_from_root_system: self.jn_system_from_root_system.read().unwrap().clone(),
91 jn_workspace_from_root_workspace: self
92 .jn_workspace_from_root_workspace
93 .read()
94 .unwrap()
95 .clone(),
96 jn_entity_from_workspace_entities: self
97 .jn_entity_from_workspace_entities
98 .read()
99 .unwrap()
100 .clone(),
101 jn_feature_from_workspace_features: self
102 .jn_feature_from_workspace_features
103 .read()
104 .unwrap()
105 .clone(),
106 jn_global_from_workspace_global: self
107 .jn_global_from_workspace_global
108 .read()
109 .unwrap()
110 .clone(),
111 jn_user_interface_from_workspace_user_interface: self
112 .jn_user_interface_from_workspace_user_interface
113 .read()
114 .unwrap()
115 .clone(),
116 jn_file_from_system_files: self.jn_file_from_system_files.read().unwrap().clone(),
117 jn_field_from_entity_fields: self.jn_field_from_entity_fields.read().unwrap().clone(),
118 jn_entity_from_entity_inherits_from: self
119 .jn_entity_from_entity_inherits_from
120 .read()
121 .unwrap()
122 .clone(),
123 jn_relationship_from_entity_relationships: self
124 .jn_relationship_from_entity_relationships
125 .read()
126 .unwrap()
127 .clone(),
128 jn_entity_from_field_entity: self.jn_entity_from_field_entity.read().unwrap().clone(),
129 jn_use_case_from_feature_use_cases: self
130 .jn_use_case_from_feature_use_cases
131 .read()
132 .unwrap()
133 .clone(),
134 jn_entity_from_file_entity: self.jn_entity_from_file_entity.read().unwrap().clone(),
135 jn_feature_from_file_feature: self.jn_feature_from_file_feature.read().unwrap().clone(),
136 jn_field_from_file_field: self.jn_field_from_file_field.read().unwrap().clone(),
137 jn_use_case_from_file_use_case: self
138 .jn_use_case_from_file_use_case
139 .read()
140 .unwrap()
141 .clone(),
142 jn_dto_from_use_case_dto_in: self.jn_dto_from_use_case_dto_in.read().unwrap().clone(),
143 jn_dto_from_use_case_dto_out: self.jn_dto_from_use_case_dto_out.read().unwrap().clone(),
144 jn_entity_from_use_case_entities: self
145 .jn_entity_from_use_case_entities
146 .read()
147 .unwrap()
148 .clone(),
149 jn_dto_field_from_dto_fields: self.jn_dto_field_from_dto_fields.read().unwrap().clone(),
150 jn_entity_from_relationship_left_entity: self
151 .jn_entity_from_relationship_left_entity
152 .read()
153 .unwrap()
154 .clone(),
155 jn_entity_from_relationship_right_entity: self
156 .jn_entity_from_relationship_right_entity
157 .read()
158 .unwrap()
159 .clone(),
160 counters: self.counters.read().unwrap().clone(),
161 }
162 }
163
164 pub fn restore(&self, snap: &HashMapStoreSnapshot) {
166 *self.roots.write().unwrap() = snap.roots.clone();
167 *self.workspaces.write().unwrap() = snap.workspaces.clone();
168 *self.systems.write().unwrap() = snap.systems.clone();
169 *self.entitys.write().unwrap() = snap.entitys.clone();
170 *self.fields.write().unwrap() = snap.fields.clone();
171 *self.features.write().unwrap() = snap.features.clone();
172 *self.files.write().unwrap() = snap.files.clone();
173 *self.use_cases.write().unwrap() = snap.use_cases.clone();
174 *self.dtos.write().unwrap() = snap.dtos.clone();
175 *self.dto_fields.write().unwrap() = snap.dto_fields.clone();
176 *self.globals.write().unwrap() = snap.globals.clone();
177 *self.relationships.write().unwrap() = snap.relationships.clone();
178 *self.user_interfaces.write().unwrap() = snap.user_interfaces.clone();
179 *self.jn_system_from_root_system.write().unwrap() = snap.jn_system_from_root_system.clone();
180 *self.jn_workspace_from_root_workspace.write().unwrap() =
181 snap.jn_workspace_from_root_workspace.clone();
182 *self.jn_entity_from_workspace_entities.write().unwrap() =
183 snap.jn_entity_from_workspace_entities.clone();
184 *self.jn_feature_from_workspace_features.write().unwrap() =
185 snap.jn_feature_from_workspace_features.clone();
186 *self.jn_global_from_workspace_global.write().unwrap() =
187 snap.jn_global_from_workspace_global.clone();
188 *self
189 .jn_user_interface_from_workspace_user_interface
190 .write()
191 .unwrap() = snap.jn_user_interface_from_workspace_user_interface.clone();
192 *self.jn_file_from_system_files.write().unwrap() = snap.jn_file_from_system_files.clone();
193 *self.jn_field_from_entity_fields.write().unwrap() =
194 snap.jn_field_from_entity_fields.clone();
195 *self.jn_entity_from_entity_inherits_from.write().unwrap() =
196 snap.jn_entity_from_entity_inherits_from.clone();
197 *self
198 .jn_relationship_from_entity_relationships
199 .write()
200 .unwrap() = snap.jn_relationship_from_entity_relationships.clone();
201 *self.jn_entity_from_field_entity.write().unwrap() =
202 snap.jn_entity_from_field_entity.clone();
203 *self.jn_use_case_from_feature_use_cases.write().unwrap() =
204 snap.jn_use_case_from_feature_use_cases.clone();
205 *self.jn_entity_from_file_entity.write().unwrap() = snap.jn_entity_from_file_entity.clone();
206 *self.jn_feature_from_file_feature.write().unwrap() =
207 snap.jn_feature_from_file_feature.clone();
208 *self.jn_field_from_file_field.write().unwrap() = snap.jn_field_from_file_field.clone();
209 *self.jn_use_case_from_file_use_case.write().unwrap() =
210 snap.jn_use_case_from_file_use_case.clone();
211 *self.jn_dto_from_use_case_dto_in.write().unwrap() =
212 snap.jn_dto_from_use_case_dto_in.clone();
213 *self.jn_dto_from_use_case_dto_out.write().unwrap() =
214 snap.jn_dto_from_use_case_dto_out.clone();
215 *self.jn_entity_from_use_case_entities.write().unwrap() =
216 snap.jn_entity_from_use_case_entities.clone();
217 *self.jn_dto_field_from_dto_fields.write().unwrap() =
218 snap.jn_dto_field_from_dto_fields.clone();
219 *self
220 .jn_entity_from_relationship_left_entity
221 .write()
222 .unwrap() = snap.jn_entity_from_relationship_left_entity.clone();
223 *self
224 .jn_entity_from_relationship_right_entity
225 .write()
226 .unwrap() = snap.jn_entity_from_relationship_right_entity.clone();
227 *self.counters.write().unwrap() = snap.counters.clone();
228 }
229
230 pub fn create_savepoint(&self) -> u64 {
233 let snap = self.snapshot();
234 let mut id_counter = self.next_savepoint_id.write().unwrap();
235 let id = *id_counter;
236 *id_counter += 1;
237 self.savepoints.write().unwrap().insert(id, snap);
238 id
239 }
240
241 pub fn restore_savepoint(&self, savepoint_id: u64) {
243 let snap = self
244 .savepoints
245 .read()
246 .unwrap()
247 .get(&savepoint_id)
248 .expect("savepoint not found")
249 .clone();
250 self.restore(&snap);
251 }
252
253 pub fn discard_savepoint(&self, savepoint_id: u64) {
255 self.savepoints.write().unwrap().remove(&savepoint_id);
256 }
257
258 pub(crate) fn next_id(&self, entity_name: &str) -> EntityId {
260 let mut counters = self.counters.write().unwrap();
261 let counter = counters.entry(entity_name.to_string()).or_insert(1);
262 let id = *counter;
263 *counter += 1;
264 id
265 }
266
267 pub fn restore_without_counters(&self, snap: &HashMapStoreSnapshot) {
270 *self.roots.write().unwrap() = snap.roots.clone();
271 *self.workspaces.write().unwrap() = snap.workspaces.clone();
272 *self.systems.write().unwrap() = snap.systems.clone();
273 *self.entitys.write().unwrap() = snap.entitys.clone();
274 *self.fields.write().unwrap() = snap.fields.clone();
275 *self.features.write().unwrap() = snap.features.clone();
276 *self.files.write().unwrap() = snap.files.clone();
277 *self.use_cases.write().unwrap() = snap.use_cases.clone();
278 *self.dtos.write().unwrap() = snap.dtos.clone();
279 *self.dto_fields.write().unwrap() = snap.dto_fields.clone();
280 *self.globals.write().unwrap() = snap.globals.clone();
281 *self.relationships.write().unwrap() = snap.relationships.clone();
282 *self.user_interfaces.write().unwrap() = snap.user_interfaces.clone();
283 *self.jn_system_from_root_system.write().unwrap() = snap.jn_system_from_root_system.clone();
284 *self.jn_workspace_from_root_workspace.write().unwrap() =
285 snap.jn_workspace_from_root_workspace.clone();
286 *self.jn_entity_from_workspace_entities.write().unwrap() =
287 snap.jn_entity_from_workspace_entities.clone();
288 *self.jn_feature_from_workspace_features.write().unwrap() =
289 snap.jn_feature_from_workspace_features.clone();
290 *self.jn_global_from_workspace_global.write().unwrap() =
291 snap.jn_global_from_workspace_global.clone();
292 *self
293 .jn_user_interface_from_workspace_user_interface
294 .write()
295 .unwrap() = snap.jn_user_interface_from_workspace_user_interface.clone();
296 *self.jn_file_from_system_files.write().unwrap() = snap.jn_file_from_system_files.clone();
297 *self.jn_field_from_entity_fields.write().unwrap() =
298 snap.jn_field_from_entity_fields.clone();
299 *self.jn_entity_from_entity_inherits_from.write().unwrap() =
300 snap.jn_entity_from_entity_inherits_from.clone();
301 *self
302 .jn_relationship_from_entity_relationships
303 .write()
304 .unwrap() = snap.jn_relationship_from_entity_relationships.clone();
305 *self.jn_entity_from_field_entity.write().unwrap() =
306 snap.jn_entity_from_field_entity.clone();
307 *self.jn_use_case_from_feature_use_cases.write().unwrap() =
308 snap.jn_use_case_from_feature_use_cases.clone();
309 *self.jn_entity_from_file_entity.write().unwrap() = snap.jn_entity_from_file_entity.clone();
310 *self.jn_feature_from_file_feature.write().unwrap() =
311 snap.jn_feature_from_file_feature.clone();
312 *self.jn_field_from_file_field.write().unwrap() = snap.jn_field_from_file_field.clone();
313 *self.jn_use_case_from_file_use_case.write().unwrap() =
314 snap.jn_use_case_from_file_use_case.clone();
315 *self.jn_dto_from_use_case_dto_in.write().unwrap() =
316 snap.jn_dto_from_use_case_dto_in.clone();
317 *self.jn_dto_from_use_case_dto_out.write().unwrap() =
318 snap.jn_dto_from_use_case_dto_out.clone();
319 *self.jn_entity_from_use_case_entities.write().unwrap() =
320 snap.jn_entity_from_use_case_entities.clone();
321 *self.jn_dto_field_from_dto_fields.write().unwrap() =
322 snap.jn_dto_field_from_dto_fields.clone();
323 *self
324 .jn_entity_from_relationship_left_entity
325 .write()
326 .unwrap() = snap.jn_entity_from_relationship_left_entity.clone();
327 *self
328 .jn_entity_from_relationship_right_entity
329 .write()
330 .unwrap() = snap.jn_entity_from_relationship_right_entity.clone();
331 }
333
334 pub fn store_snapshot(&self) -> StoreSnapshot {
336 StoreSnapshot::new(self.snapshot())
337 }
338
339 pub fn restore_store_snapshot(&self, snap: &StoreSnapshot) {
341 let s = snap
342 .downcast_ref::<HashMapStoreSnapshot>()
343 .expect("StoreSnapshot must contain HashMapStoreSnapshot");
344 self.restore_without_counters(s);
345 }
346}
347
348#[derive(Debug, Clone)]
350pub struct HashMapStoreSnapshot {
351 roots: HashMap<EntityId, Root>,
352 workspaces: HashMap<EntityId, Workspace>,
353 systems: HashMap<EntityId, System>,
354 entitys: HashMap<EntityId, Entity>,
355 fields: HashMap<EntityId, Field>,
356 features: HashMap<EntityId, Feature>,
357 files: HashMap<EntityId, File>,
358 use_cases: HashMap<EntityId, UseCase>,
359 dtos: HashMap<EntityId, Dto>,
360 dto_fields: HashMap<EntityId, DtoField>,
361 globals: HashMap<EntityId, Global>,
362 relationships: HashMap<EntityId, Relationship>,
363 user_interfaces: HashMap<EntityId, UserInterface>,
364 jn_system_from_root_system: HashMap<EntityId, Vec<EntityId>>,
365 jn_workspace_from_root_workspace: HashMap<EntityId, Vec<EntityId>>,
366 jn_entity_from_workspace_entities: HashMap<EntityId, Vec<EntityId>>,
367 jn_feature_from_workspace_features: HashMap<EntityId, Vec<EntityId>>,
368 jn_global_from_workspace_global: HashMap<EntityId, Vec<EntityId>>,
369 jn_user_interface_from_workspace_user_interface: HashMap<EntityId, Vec<EntityId>>,
370 jn_file_from_system_files: HashMap<EntityId, Vec<EntityId>>,
371 jn_field_from_entity_fields: HashMap<EntityId, Vec<EntityId>>,
372 jn_entity_from_entity_inherits_from: HashMap<EntityId, Vec<EntityId>>,
373 jn_relationship_from_entity_relationships: HashMap<EntityId, Vec<EntityId>>,
374 jn_entity_from_field_entity: HashMap<EntityId, Vec<EntityId>>,
375 jn_use_case_from_feature_use_cases: HashMap<EntityId, Vec<EntityId>>,
376 jn_entity_from_file_entity: HashMap<EntityId, Vec<EntityId>>,
377 jn_feature_from_file_feature: HashMap<EntityId, Vec<EntityId>>,
378 jn_field_from_file_field: HashMap<EntityId, Vec<EntityId>>,
379 jn_use_case_from_file_use_case: HashMap<EntityId, Vec<EntityId>>,
380 jn_dto_from_use_case_dto_in: HashMap<EntityId, Vec<EntityId>>,
381 jn_dto_from_use_case_dto_out: HashMap<EntityId, Vec<EntityId>>,
382 jn_entity_from_use_case_entities: HashMap<EntityId, Vec<EntityId>>,
383 jn_dto_field_from_dto_fields: HashMap<EntityId, Vec<EntityId>>,
384 jn_entity_from_relationship_left_entity: HashMap<EntityId, Vec<EntityId>>,
385 jn_entity_from_relationship_right_entity: HashMap<EntityId, Vec<EntityId>>,
386 counters: std::collections::HashMap<String, EntityId>,
387}
388
389impl StoreSnapshotTrait for HashMapStoreSnapshot {
390 fn clone_box(&self) -> Box<dyn StoreSnapshotTrait> {
391 Box::new(self.clone())
392 }
393
394 fn as_any(&self) -> &dyn std::any::Any {
395 self
396 }
397}
398
399pub(crate) fn delete_from_backward_junction(
404 junction: &RwLock<HashMap<EntityId, Vec<EntityId>>>,
405 id: &EntityId,
406) {
407 let mut jn = junction.write().unwrap();
408 let keys: Vec<EntityId> = jn.keys().copied().collect();
409 for k in keys {
410 if let Some(right_ids) = jn.get(&k)
411 && right_ids.contains(id)
412 {
413 let filtered: Vec<EntityId> =
414 right_ids.iter().copied().filter(|eid| eid != id).collect();
415 jn.insert(k, filtered);
416 }
417 }
418}
419
420pub(crate) fn junction_get(
421 junction: &RwLock<HashMap<EntityId, Vec<EntityId>>>,
422 id: &EntityId,
423) -> Vec<EntityId> {
424 junction
425 .read()
426 .unwrap()
427 .get(id)
428 .cloned()
429 .unwrap_or_default()
430}
431
432pub(crate) fn junction_set(
433 junction: &RwLock<HashMap<EntityId, Vec<EntityId>>>,
434 id: EntityId,
435 ids: Vec<EntityId>,
436) {
437 junction.write().unwrap().insert(id, ids);
438}
439
440pub(crate) fn junction_remove(junction: &RwLock<HashMap<EntityId, Vec<EntityId>>>, id: &EntityId) {
441 junction.write().unwrap().remove(id);
442}
443
444pub(crate) fn junction_get_relationships_from_right_ids(
445 junction: &RwLock<HashMap<EntityId, Vec<EntityId>>>,
446 right_ids: &[EntityId],
447) -> Vec<(EntityId, Vec<EntityId>)> {
448 let jn = junction.read().unwrap();
449 jn.iter()
450 .filter(|(_, rids)| right_ids.iter().any(|eid| rids.contains(eid)))
451 .map(|(left_id, rids)| (*left_id, rids.clone()))
452 .collect()
453}
454
455pub(crate) fn junction_move_ids(
456 junction: &RwLock<HashMap<EntityId, Vec<EntityId>>>,
457 id: &EntityId,
458 ids_to_move: &[EntityId],
459 new_index: i32,
460) -> Vec<EntityId> {
461 let current = junction_get(junction, id);
462 if ids_to_move.is_empty() {
463 return current;
464 }
465 let move_set: std::collections::HashSet<EntityId> = ids_to_move.iter().copied().collect();
466 let mut remaining: Vec<EntityId> = current
467 .into_iter()
468 .filter(|eid| !move_set.contains(eid))
469 .collect();
470 let insert_pos = if new_index < 0 || (new_index as usize) > remaining.len() {
471 remaining.len()
472 } else {
473 new_index as usize
474 };
475 for (i, &eid) in ids_to_move.iter().enumerate() {
476 remaining.insert(insert_pos + i, eid);
477 }
478 junction_set(junction, *id, remaining.clone());
479 remaining
480}
481
482#[macro_export]
488macro_rules! impl_relationship_methods {
489 ($table_type:ty, $field_enum:ty) => {
490 fn get_relationship(
491 &self,
492 id: &$crate::types::EntityId,
493 field: &$field_enum,
494 ) -> Result<Vec<$crate::types::EntityId>, $crate::error::RepositoryError> {
495 Ok($crate::database::hashmap_store::junction_get(
496 self.resolve_junction(field),
497 id,
498 ))
499 }
500
501 fn get_relationship_many(
502 &self,
503 ids: &[$crate::types::EntityId],
504 field: &$field_enum,
505 ) -> Result<
506 std::collections::HashMap<$crate::types::EntityId, Vec<$crate::types::EntityId>>,
507 $crate::error::RepositoryError,
508 > {
509 let jn = self.resolve_junction(field);
510 let mut map = std::collections::HashMap::new();
511 for id in ids {
512 map.insert(*id, $crate::database::hashmap_store::junction_get(jn, id));
513 }
514 Ok(map)
515 }
516
517 fn get_relationship_count(
518 &self,
519 id: &$crate::types::EntityId,
520 field: &$field_enum,
521 ) -> Result<usize, $crate::error::RepositoryError> {
522 Ok(
523 $crate::database::hashmap_store::junction_get(self.resolve_junction(field), id)
524 .len(),
525 )
526 }
527
528 fn get_relationship_in_range(
529 &self,
530 id: &$crate::types::EntityId,
531 field: &$field_enum,
532 offset: usize,
533 limit: usize,
534 ) -> Result<Vec<$crate::types::EntityId>, $crate::error::RepositoryError> {
535 let all =
536 $crate::database::hashmap_store::junction_get(self.resolve_junction(field), id);
537 Ok(all.into_iter().skip(offset).take(limit).collect())
538 }
539
540 fn get_relationships_from_right_ids(
541 &self,
542 field: &$field_enum,
543 right_ids: &[$crate::types::EntityId],
544 ) -> Result<
545 Vec<($crate::types::EntityId, Vec<$crate::types::EntityId>)>,
546 $crate::error::RepositoryError,
547 > {
548 Ok(
549 $crate::database::hashmap_store::junction_get_relationships_from_right_ids(
550 self.resolve_junction(field),
551 right_ids,
552 ),
553 )
554 }
555 };
556}
557
558#[macro_export]
559macro_rules! impl_write_relationship_methods {
560 ($table_type:ty, $field_enum:ty) => {
561 $crate::impl_relationship_methods!($table_type, $field_enum);
562
563 fn set_relationship_multi(
564 &mut self,
565 field: &$field_enum,
566 relationships: Vec<($crate::types::EntityId, Vec<$crate::types::EntityId>)>,
567 ) -> Result<(), $crate::error::RepositoryError> {
568 let jn = self.resolve_junction(field);
569 for (left_id, entities) in relationships {
570 $crate::database::hashmap_store::junction_set(jn, left_id, entities);
571 }
572 Ok(())
573 }
574
575 fn set_relationship(
576 &mut self,
577 id: &$crate::types::EntityId,
578 field: &$field_enum,
579 right_ids: &[$crate::types::EntityId],
580 ) -> Result<(), $crate::error::RepositoryError> {
581 $crate::database::hashmap_store::junction_set(
582 self.resolve_junction(field),
583 *id,
584 right_ids.to_vec(),
585 );
586 Ok(())
587 }
588
589 fn move_relationship_ids(
590 &mut self,
591 id: &$crate::types::EntityId,
592 field: &$field_enum,
593 ids_to_move: &[$crate::types::EntityId],
594 new_index: i32,
595 ) -> Result<Vec<$crate::types::EntityId>, $crate::error::RepositoryError> {
596 Ok($crate::database::hashmap_store::junction_move_ids(
597 self.resolve_junction(field),
598 id,
599 ids_to_move,
600 new_index,
601 ))
602 }
603 };
604}
605
606#[macro_export]
611macro_rules! impl_leaf_entity_table {
612 (
613 entity: $Entity:ident,
614 entity_name: $entity_name:expr,
615 store_field: $store_field:ident,
616 table_trait: $TableTrait:ident,
617 table_ro_trait: $TableROTrait:ident,
618 table_struct: $TableStruct:ident,
619 table_ro_struct: $TableROStruct:ident,
620 backward_junctions: [ $( ($bj_field:ident) ),* $(,)? ],
621 ) => {
622 pub struct $TableStruct<'a> {
623 store: &'a $crate::database::hashmap_store::HashMapStore,
624 }
625
626 impl<'a> $TableStruct<'a> {
627 pub fn new(store: &'a $crate::database::hashmap_store::HashMapStore) -> Self {
628 Self { store }
629 }
630 }
631
632 impl<'a> $TableTrait for $TableStruct<'a> {
633 fn create(&mut self, entity: &$Entity) -> Result<$Entity, $crate::error::RepositoryError> {
634 self.create_multi(std::slice::from_ref(entity))
635 .map(|v| v.into_iter().next().unwrap())
636 }
637
638 fn create_multi(&mut self, entities: &[$Entity]) -> Result<Vec<$Entity>, $crate::error::RepositoryError> {
639 let mut created = Vec::with_capacity(entities.len());
640 let mut map = self.store.$store_field.write().unwrap();
641
642 for entity in entities {
643 let new_entity = if entity.id == $crate::types::EntityId::default() {
644 let id = self.store.next_id($entity_name);
645 $Entity {
646 id,
647 ..entity.clone()
648 }
649 } else {
650 if map.contains_key(&entity.id) {
651 return Err($crate::error::RepositoryError::DuplicateId {
652 entity: stringify!($Entity),
653 id: entity.id,
654 });
655 }
656 entity.clone()
657 };
658
659 map.insert(new_entity.id, new_entity.clone());
660 created.push(new_entity);
661 }
662 Ok(created)
663 }
664
665 fn get(&self, id: &$crate::types::EntityId) -> Result<Option<$Entity>, $crate::error::RepositoryError> {
666 Ok(self.store.$store_field.read().unwrap().get(id).cloned())
667 }
668
669 fn get_multi(&self, ids: &[$crate::types::EntityId]) -> Result<Vec<Option<$Entity>>, $crate::error::RepositoryError> {
670 let map = self.store.$store_field.read().unwrap();
671 Ok(ids.iter().map(|id| map.get(id).cloned()).collect())
672 }
673
674 fn get_all(&self) -> Result<Vec<$Entity>, $crate::error::RepositoryError> {
675 Ok(self.store.$store_field.read().unwrap().values().cloned().collect())
676 }
677
678 fn update(&mut self, entity: &$Entity) -> Result<$Entity, $crate::error::RepositoryError> {
679 self.update_multi(std::slice::from_ref(entity))
680 .map(|v| v.into_iter().next().unwrap())
681 }
682
683 fn update_multi(&mut self, entities: &[$Entity]) -> Result<Vec<$Entity>, $crate::error::RepositoryError> {
684 let mut map = self.store.$store_field.write().unwrap();
685 let mut result = Vec::with_capacity(entities.len());
686 for entity in entities {
687 map.insert(entity.id, entity.clone());
688 result.push(entity.clone());
689 }
690 Ok(result)
691 }
692
693 fn update_with_relationships(&mut self, entity: &$Entity) -> Result<$Entity, $crate::error::RepositoryError> {
694 self.update(entity)
695 }
696
697 fn update_with_relationships_multi(&mut self, entities: &[$Entity]) -> Result<Vec<$Entity>, $crate::error::RepositoryError> {
698 self.update_multi(entities)
699 }
700
701 fn remove(&mut self, id: &$crate::types::EntityId) -> Result<(), $crate::error::RepositoryError> {
702 self.remove_multi(std::slice::from_ref(id))
703 }
704
705 fn remove_multi(&mut self, ids: &[$crate::types::EntityId]) -> Result<(), $crate::error::RepositoryError> {
706 let mut map = self.store.$store_field.write().unwrap();
707 for id in ids {
708 map.remove(id);
709 $(
710 $crate::database::hashmap_store::delete_from_backward_junction(&self.store.$bj_field, id);
711 )*
712 }
713 Ok(())
714 }
715 }
716
717 pub struct $TableROStruct<'a> {
718 store: &'a $crate::database::hashmap_store::HashMapStore,
719 }
720
721 impl<'a> $TableROStruct<'a> {
722 pub fn new(store: &'a $crate::database::hashmap_store::HashMapStore) -> Self {
723 Self { store }
724 }
725 }
726
727 impl<'a> $TableROTrait for $TableROStruct<'a> {
728 fn get(&self, id: &$crate::types::EntityId) -> Result<Option<$Entity>, $crate::error::RepositoryError> {
729 Ok(self.store.$store_field.read().unwrap().get(id).cloned())
730 }
731
732 fn get_multi(&self, ids: &[$crate::types::EntityId]) -> Result<Vec<Option<$Entity>>, $crate::error::RepositoryError> {
733 let map = self.store.$store_field.read().unwrap();
734 Ok(ids.iter().map(|id| map.get(id).cloned()).collect())
735 }
736
737 fn get_all(&self) -> Result<Vec<$Entity>, $crate::error::RepositoryError> {
738 Ok(self.store.$store_field.read().unwrap().values().cloned().collect())
739 }
740 }
741 };
742}