1use std::fmt::Display;
4
5use crate::{
6 database::hashmap_store::HashMapStoreSnapshot,
7 database::hashmap_store::{read_or_recover, write_or_recover},
13 database::transactions::Transaction,
14 direct_access::repository_factory,
15 entities::UseCase,
16 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
17 snapshot::EntityTreeSnapshot,
18 types::EntityId,
19};
20
21use crate::direct_access::feature::FeatureRelationshipField;
22use crate::error::RepositoryError;
23use serde::{Deserialize, Serialize};
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub enum UseCaseRelationshipField {
27 DtoIn,
28 DtoOut,
29 Entities,
30}
31
32impl Display for UseCaseRelationshipField {
33 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
34 write!(f, "{:?}", self)
35 }
36}
37
38pub trait UseCaseTable {
39 fn create(&mut self, entity: &UseCase) -> Result<UseCase, RepositoryError>;
40 fn create_multi(&mut self, entities: &[UseCase]) -> Result<Vec<UseCase>, RepositoryError>;
41 fn get(&self, id: &EntityId) -> Result<Option<UseCase>, RepositoryError>;
42 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<UseCase>>, RepositoryError>;
43 fn get_all(&self) -> Result<Vec<UseCase>, RepositoryError>;
44 fn update(&mut self, entity: &UseCase) -> Result<UseCase, RepositoryError>;
45 fn update_multi(&mut self, entities: &[UseCase]) -> Result<Vec<UseCase>, RepositoryError>;
46 fn update_with_relationships(&mut self, entity: &UseCase) -> Result<UseCase, RepositoryError>;
47 fn update_with_relationships_multi(
48 &mut self,
49 entities: &[UseCase],
50 ) -> Result<Vec<UseCase>, RepositoryError>;
51 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
52 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
53 fn get_relationship(
54 &self,
55 id: &EntityId,
56 field: &UseCaseRelationshipField,
57 ) -> Result<Vec<EntityId>, RepositoryError>;
58 fn get_relationship_many(
59 &self,
60 ids: &[EntityId],
61 field: &UseCaseRelationshipField,
62 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
63 fn get_relationship_count(
64 &self,
65 id: &EntityId,
66 field: &UseCaseRelationshipField,
67 ) -> Result<usize, RepositoryError>;
68 fn get_relationship_in_range(
69 &self,
70 id: &EntityId,
71 field: &UseCaseRelationshipField,
72 offset: usize,
73 limit: usize,
74 ) -> Result<Vec<EntityId>, RepositoryError>;
75 fn get_relationships_from_right_ids(
76 &self,
77 field: &UseCaseRelationshipField,
78 right_ids: &[EntityId],
79 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
80 fn set_relationship_multi(
81 &mut self,
82 field: &UseCaseRelationshipField,
83 relationships: Vec<(EntityId, Vec<EntityId>)>,
84 ) -> Result<(), RepositoryError>;
85 fn set_relationship(
86 &mut self,
87 id: &EntityId,
88 field: &UseCaseRelationshipField,
89 right_ids: &[EntityId],
90 ) -> Result<(), RepositoryError>;
91 fn move_relationship_ids(
92 &mut self,
93 id: &EntityId,
94 field: &UseCaseRelationshipField,
95 ids_to_move: &[EntityId],
96 new_index: i32,
97 ) -> Result<Vec<EntityId>, RepositoryError>;
98}
99
100pub trait UseCaseTableRO {
101 fn get(&self, id: &EntityId) -> Result<Option<UseCase>, RepositoryError>;
102 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<UseCase>>, RepositoryError>;
103 fn get_all(&self) -> Result<Vec<UseCase>, RepositoryError>;
104 fn get_relationship(
105 &self,
106 id: &EntityId,
107 field: &UseCaseRelationshipField,
108 ) -> Result<Vec<EntityId>, RepositoryError>;
109 fn get_relationship_many(
110 &self,
111 ids: &[EntityId],
112 field: &UseCaseRelationshipField,
113 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
114 fn get_relationship_count(
115 &self,
116 id: &EntityId,
117 field: &UseCaseRelationshipField,
118 ) -> Result<usize, RepositoryError>;
119 fn get_relationship_in_range(
120 &self,
121 id: &EntityId,
122 field: &UseCaseRelationshipField,
123 offset: usize,
124 limit: usize,
125 ) -> Result<Vec<EntityId>, RepositoryError>;
126 fn get_relationships_from_right_ids(
127 &self,
128 field: &UseCaseRelationshipField,
129 right_ids: &[EntityId],
130 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
131}
132
133pub struct UseCaseRepository<'a> {
134 table: Box<dyn UseCaseTable + 'a>,
135 transaction: &'a Transaction,
136}
137
138impl<'a> UseCaseRepository<'a> {
139 pub fn new(table: Box<dyn UseCaseTable + 'a>, transaction: &'a Transaction) -> Self {
140 UseCaseRepository { table, transaction }
141 }
142
143 pub fn create_orphan(
144 &mut self,
145 event_buffer: &mut EventBuffer,
146 entity: &UseCase,
147 ) -> Result<UseCase, RepositoryError> {
148 let new = self.table.create(entity)?;
149 event_buffer.push(Event {
150 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Created)),
151 ids: vec![new.id],
152 data: None,
153 });
154 Ok(new)
155 }
156
157 pub fn create_orphan_multi(
158 &mut self,
159 event_buffer: &mut EventBuffer,
160 entities: &[UseCase],
161 ) -> Result<Vec<UseCase>, RepositoryError> {
162 let new_entities = self.table.create_multi(entities)?;
163 event_buffer.push(Event {
164 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Created)),
165 ids: new_entities.iter().map(|e| e.id).collect(),
166 data: None,
167 });
168 Ok(new_entities)
169 }
170 pub fn create(
171 &mut self,
172 event_buffer: &mut EventBuffer,
173 entity: &UseCase,
174 owner_id: EntityId,
175 index: i32,
176 ) -> Result<UseCase, RepositoryError> {
177 let new = self.table.create(entity)?;
178 let created_id = new.id;
179
180 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
181 if index >= 0 && (index as usize) < relationship_ids.len() {
183 relationship_ids.insert(index as usize, created_id);
184 } else {
185 relationship_ids.push(created_id);
186 }
187
188 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
189 event_buffer.push(Event {
190 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Created)),
191 ids: vec![created_id],
192 data: None,
193 });
194 Ok(new)
195 }
196
197 pub fn create_multi(
198 &mut self,
199 event_buffer: &mut EventBuffer,
200 entities: &[UseCase],
201 owner_id: EntityId,
202 index: i32,
203 ) -> Result<Vec<UseCase>, RepositoryError> {
204 let new_entities = self.table.create_multi(entities)?;
205 let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
206
207 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
208 if index >= 0 && (index as usize) < relationship_ids.len() {
209 for (i, id) in created_ids.iter().enumerate() {
210 relationship_ids.insert(index as usize + i, *id);
211 }
212 } else {
213 relationship_ids.extend(created_ids.iter());
214 }
215
216 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
217 event_buffer.push(Event {
218 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Created)),
219 ids: created_ids,
220 data: None,
221 });
222 Ok(new_entities)
223 }
224
225 pub fn get(&self, id: &EntityId) -> Result<Option<UseCase>, RepositoryError> {
226 self.table.get(id)
227 }
228 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<UseCase>>, RepositoryError> {
229 self.table.get_multi(ids)
230 }
231 pub fn get_all(&self) -> Result<Vec<UseCase>, RepositoryError> {
232 self.table.get_all()
233 }
234
235 pub fn update(
236 &mut self,
237 event_buffer: &mut EventBuffer,
238 entity: &UseCase,
239 ) -> Result<UseCase, RepositoryError> {
240 let updated = self.table.update(entity)?;
241 event_buffer.push(Event {
242 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
243 ids: vec![updated.id],
244 data: None,
245 });
246 Ok(updated)
247 }
248
249 pub fn update_multi(
250 &mut self,
251 event_buffer: &mut EventBuffer,
252 entities: &[UseCase],
253 ) -> Result<Vec<UseCase>, RepositoryError> {
254 let updated = self.table.update_multi(entities)?;
255 event_buffer.push(Event {
256 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
257 ids: updated.iter().map(|e| e.id).collect(),
258 data: None,
259 });
260 Ok(updated)
261 }
262
263 pub fn update_with_relationships(
264 &mut self,
265 event_buffer: &mut EventBuffer,
266 entity: &UseCase,
267 ) -> Result<UseCase, RepositoryError> {
268 let updated = self.table.update_with_relationships(entity)?;
269 event_buffer.push(Event {
270 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
271 ids: vec![updated.id],
272 data: None,
273 });
274 Ok(updated)
275 }
276
277 pub fn update_with_relationships_multi(
278 &mut self,
279 event_buffer: &mut EventBuffer,
280 entities: &[UseCase],
281 ) -> Result<Vec<UseCase>, RepositoryError> {
282 let updated = self.table.update_with_relationships_multi(entities)?;
283 event_buffer.push(Event {
284 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
285 ids: updated.iter().map(|e| e.id).collect(),
286 data: None,
287 });
288 Ok(updated)
289 }
290
291 pub fn remove(
292 &mut self,
293 event_buffer: &mut EventBuffer,
294 id: &EntityId,
295 ) -> Result<(), RepositoryError> {
296 let entity = match self.table.get(id)? {
297 Some(e) => e,
298 None => return Ok(()),
299 };
300 let dto_in = entity.dto_in;
303 let dto_out = entity.dto_out;
304
305 if let Some(dto_in_id) = dto_in {
308 repository_factory::write::create_dto_repository(self.transaction)?
309 .remove(event_buffer, &dto_in_id)?;
310 }
311 if let Some(dto_out_id) = dto_out {
312 repository_factory::write::create_dto_repository(self.transaction)?
313 .remove(event_buffer, &dto_out_id)?;
314 }
315 let affected_owner_ids: Vec<EntityId> = {
317 let owner_repo =
318 repository_factory::write::create_feature_repository(self.transaction)?;
319 owner_repo
320 .get_relationships_from_right_ids(&FeatureRelationshipField::UseCases, &[*id])?
321 .into_iter()
322 .map(|(owner_id, _)| owner_id)
323 .collect()
324 };
325 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
327 std::collections::HashMap::new();
328 for owner_id in &affected_owner_ids {
329 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
330 }
331
332 self.table.remove(id)?;
334 event_buffer.push(Event {
335 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Removed)),
336 ids: vec![*id],
337 data: None,
338 });
339 for owner_id in &affected_owner_ids {
341 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
342 let updated: Vec<EntityId> =
343 rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
344 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
345 }
346 }
347
348 Ok(())
349 }
350
351 pub fn remove_multi(
352 &mut self,
353 event_buffer: &mut EventBuffer,
354 ids: &[EntityId],
355 ) -> Result<(), RepositoryError> {
356 let entities = self.table.get_multi(ids)?;
357 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
358 return Ok(());
359 }
360
361 let dto_in_ids: Vec<EntityId> = entities
364 .iter()
365 .filter_map(|entity| entity.as_ref().and_then(|entity| entity.dto_in))
366 .collect();
367 let dto_out_ids: Vec<EntityId> = entities
368 .iter()
369 .filter_map(|entity| entity.as_ref().and_then(|entity| entity.dto_out))
370 .collect();
371
372 repository_factory::write::create_dto_repository(self.transaction)?
375 .remove_multi(event_buffer, &dto_in_ids)?;
376 repository_factory::write::create_dto_repository(self.transaction)?
377 .remove_multi(event_buffer, &dto_out_ids)?;
378 let affected_owner_ids: Vec<EntityId> = {
380 let owner_repo =
381 repository_factory::write::create_feature_repository(self.transaction)?;
382 owner_repo
383 .get_relationships_from_right_ids(&FeatureRelationshipField::UseCases, ids)?
384 .into_iter()
385 .map(|(owner_id, _)| owner_id)
386 .collect()
387 };
388 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
390 std::collections::HashMap::new();
391 for owner_id in &affected_owner_ids {
392 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
393 }
394
395 self.table.remove_multi(ids)?;
396 event_buffer.push(Event {
397 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Removed)),
398 ids: ids.into(),
399 data: None,
400 });
401 {
403 let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
404 for owner_id in &affected_owner_ids {
405 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
406 let updated: Vec<EntityId> = rel_ids
407 .iter()
408 .copied()
409 .filter(|rid| !removed_set.contains(rid))
410 .collect();
411 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
412 }
413 }
414 }
415
416 Ok(())
417 }
418 pub fn get_relationship(
419 &self,
420 id: &EntityId,
421 field: &UseCaseRelationshipField,
422 ) -> Result<Vec<EntityId>, RepositoryError> {
423 self.table.get_relationship(id, field)
424 }
425 pub fn get_relationship_many(
426 &self,
427 ids: &[EntityId],
428 field: &UseCaseRelationshipField,
429 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
430 self.table.get_relationship_many(ids, field)
431 }
432 pub fn get_relationship_count(
433 &self,
434 id: &EntityId,
435 field: &UseCaseRelationshipField,
436 ) -> Result<usize, RepositoryError> {
437 self.table.get_relationship_count(id, field)
438 }
439 pub fn get_relationship_in_range(
440 &self,
441 id: &EntityId,
442 field: &UseCaseRelationshipField,
443 offset: usize,
444 limit: usize,
445 ) -> Result<Vec<EntityId>, RepositoryError> {
446 self.table
447 .get_relationship_in_range(id, field, offset, limit)
448 }
449 pub fn get_relationships_from_right_ids(
450 &self,
451 field: &UseCaseRelationshipField,
452 right_ids: &[EntityId],
453 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
454 self.table
455 .get_relationships_from_right_ids(field, right_ids)
456 }
457
458 pub fn set_relationship_multi(
459 &mut self,
460 event_buffer: &mut EventBuffer,
461 field: &UseCaseRelationshipField,
462 relationships: Vec<(EntityId, Vec<EntityId>)>,
463 ) -> Result<(), RepositoryError> {
464 let all_right_ids: Vec<EntityId> = relationships
466 .iter()
467 .flat_map(|(_, ids)| ids.iter().copied())
468 .collect();
469 if !all_right_ids.is_empty() {
470 match field {
471 UseCaseRelationshipField::DtoIn => {
472 let child_repo =
473 repository_factory::write::create_dto_repository(self.transaction)?;
474 let found = child_repo.get_multi(&all_right_ids)?;
475 let missing: Vec<_> = all_right_ids
476 .iter()
477 .zip(found.iter())
478 .filter(|(_, entity)| entity.is_none())
479 .map(|(id, _)| *id)
480 .collect();
481 if !missing.is_empty() {
482 return Err(RepositoryError::MissingRelationshipTarget {
483 operation: "set_relationship_multi",
484 ids: missing,
485 });
486 }
487 }
488 UseCaseRelationshipField::DtoOut => {
489 let child_repo =
490 repository_factory::write::create_dto_repository(self.transaction)?;
491 let found = child_repo.get_multi(&all_right_ids)?;
492 let missing: Vec<_> = all_right_ids
493 .iter()
494 .zip(found.iter())
495 .filter(|(_, entity)| entity.is_none())
496 .map(|(id, _)| *id)
497 .collect();
498 if !missing.is_empty() {
499 return Err(RepositoryError::MissingRelationshipTarget {
500 operation: "set_relationship_multi",
501 ids: missing,
502 });
503 }
504 }
505 UseCaseRelationshipField::Entities => {
506 let child_repo =
507 repository_factory::write::create_entity_repository(self.transaction)?;
508 let found = child_repo.get_multi(&all_right_ids)?;
509 let missing: Vec<_> = all_right_ids
510 .iter()
511 .zip(found.iter())
512 .filter(|(_, entity)| entity.is_none())
513 .map(|(id, _)| *id)
514 .collect();
515 if !missing.is_empty() {
516 return Err(RepositoryError::MissingRelationshipTarget {
517 operation: "set_relationship_multi",
518 ids: missing,
519 });
520 }
521 }
522 }
523 }
524 self.table
525 .set_relationship_multi(field, relationships.clone())?;
526 for (left_id, right_ids) in relationships {
527 event_buffer.push(Event {
528 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
529 ids: vec![left_id],
530 data: Some(format!(
531 "{}:{}",
532 field,
533 right_ids
534 .iter()
535 .map(|id| id.to_string())
536 .collect::<Vec<_>>()
537 .join(",")
538 )),
539 });
540 }
541 Ok(())
542 }
543
544 pub fn set_relationship(
545 &mut self,
546 event_buffer: &mut EventBuffer,
547 id: &EntityId,
548 field: &UseCaseRelationshipField,
549 right_ids: &[EntityId],
550 ) -> Result<(), RepositoryError> {
551 if !right_ids.is_empty() {
553 match field {
554 UseCaseRelationshipField::DtoIn => {
555 let child_repo =
556 repository_factory::write::create_dto_repository(self.transaction)?;
557 let found = child_repo.get_multi(right_ids)?;
558 let missing: Vec<_> = right_ids
559 .iter()
560 .zip(found.iter())
561 .filter(|(_, entity)| entity.is_none())
562 .map(|(id, _)| *id)
563 .collect();
564 if !missing.is_empty() {
565 return Err(RepositoryError::MissingRelationshipTarget {
566 operation: "set_relationship",
567 ids: missing,
568 });
569 }
570 }
571 UseCaseRelationshipField::DtoOut => {
572 let child_repo =
573 repository_factory::write::create_dto_repository(self.transaction)?;
574 let found = child_repo.get_multi(right_ids)?;
575 let missing: Vec<_> = right_ids
576 .iter()
577 .zip(found.iter())
578 .filter(|(_, entity)| entity.is_none())
579 .map(|(id, _)| *id)
580 .collect();
581 if !missing.is_empty() {
582 return Err(RepositoryError::MissingRelationshipTarget {
583 operation: "set_relationship",
584 ids: missing,
585 });
586 }
587 }
588 UseCaseRelationshipField::Entities => {
589 let child_repo =
590 repository_factory::write::create_entity_repository(self.transaction)?;
591 let found = child_repo.get_multi(right_ids)?;
592 let missing: Vec<_> = right_ids
593 .iter()
594 .zip(found.iter())
595 .filter(|(_, entity)| entity.is_none())
596 .map(|(id, _)| *id)
597 .collect();
598 if !missing.is_empty() {
599 return Err(RepositoryError::MissingRelationshipTarget {
600 operation: "set_relationship",
601 ids: missing,
602 });
603 }
604 }
605 }
606 }
607 self.table.set_relationship(id, field, right_ids)?;
608 event_buffer.push(Event {
609 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
610 ids: vec![*id],
611 data: Some(format!(
612 "{}:{}",
613 field,
614 right_ids
615 .iter()
616 .map(|id| id.to_string())
617 .collect::<Vec<_>>()
618 .join(",")
619 )),
620 });
621 Ok(())
622 }
623
624 pub fn move_relationship_ids(
625 &mut self,
626 event_buffer: &mut EventBuffer,
627 id: &EntityId,
628 field: &UseCaseRelationshipField,
629 ids_to_move: &[EntityId],
630 new_index: i32,
631 ) -> Result<Vec<EntityId>, RepositoryError> {
632 let reordered = self
633 .table
634 .move_relationship_ids(id, field, ids_to_move, new_index)?;
635 event_buffer.push(Event {
636 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
637 ids: vec![*id],
638 data: Some(format!(
639 "{}:{}",
640 field,
641 reordered
642 .iter()
643 .map(|id| id.to_string())
644 .collect::<Vec<_>>()
645 .join(",")
646 )),
647 });
648 Ok(reordered)
649 }
650 pub fn get_relationships_from_owner(
651 &self,
652 owner_id: &EntityId,
653 ) -> Result<Vec<EntityId>, RepositoryError> {
654 let repo = repository_factory::write::create_feature_repository(self.transaction)?;
655 repo.get_relationship(owner_id, &FeatureRelationshipField::UseCases)
656 }
657
658 pub fn set_relationships_in_owner(
659 &mut self,
660 event_buffer: &mut EventBuffer,
661 owner_id: &EntityId,
662 ids: &[EntityId],
663 ) -> Result<(), RepositoryError> {
664 let mut repo = repository_factory::write::create_feature_repository(self.transaction)?;
665 repo.set_relationship(
666 event_buffer,
667 owner_id,
668 &FeatureRelationshipField::UseCases,
669 ids,
670 )
671 }
672
673 pub fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
674 let store_snap = self.transaction.snapshot_store();
676 Ok(EntityTreeSnapshot {
677 store_snapshot: Some(store_snap),
678 root_ids: ids.to_vec(),
679 })
680 }
681
682 pub fn restore(
683 &mut self,
684 event_buffer: &mut EventBuffer,
685 snap: &EntityTreeSnapshot,
686 ) -> Result<(), RepositoryError> {
687 let store_snap = snap
688 .store_snapshot
689 .as_ref()
690 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
691 let snap_store = store_snap
692 .downcast_ref::<HashMapStoreSnapshot>()
693 .ok_or_else(|| RepositoryError::Serialization("snapshot type mismatch".into()))?;
694
695 let mut visited = std::collections::HashSet::new();
698 self.restore_subtree(event_buffer, snap_store, &snap.root_ids, &mut visited)?;
699
700 self.reconcile_backref_feature_use_cases(event_buffer, snap_store, &snap.root_ids)?;
703
704 Ok(())
705 }
706
707 pub(crate) fn restore_subtree(
712 &self,
713 event_buffer: &mut EventBuffer,
714 snap: &HashMapStoreSnapshot,
715 ids: &[EntityId],
716 visited: &mut std::collections::HashSet<(&'static str, EntityId)>,
719 ) -> Result<(), RepositoryError> {
720 let ids: Vec<EntityId> = ids
721 .iter()
722 .copied()
723 .filter(|id| visited.insert(("use_case", *id)))
724 .collect();
725 if ids.is_empty() {
726 return Ok(());
727 }
728
729 let store = self.transaction.get_store();
730
731 let mut to_create: Vec<EntityId> = Vec::new(); let mut to_update: Vec<EntityId> = Vec::new(); let mut to_delete: Vec<EntityId> = Vec::new(); {
736 let live = read_or_recover(&store.use_cases);
737 for id in &ids {
738 match (snap.use_cases.contains_key(id), live.contains_key(id)) {
739 (true, false) => to_create.push(*id),
740 (true, true) => to_update.push(*id),
741 (false, true) => to_delete.push(*id),
742 (false, false) => {}
743 }
744 }
745 }
746
747 {
750 let mut child_ids: Vec<EntityId> = Vec::new();
751 for id in to_create.iter().chain(to_update.iter()) {
752 if let Some(list) = snap.jn_dto_from_use_case_dto_in.get(id) {
753 child_ids.extend(list.iter().copied());
754 }
755 }
756 {
757 let live_jn = read_or_recover(&store.jn_dto_from_use_case_dto_in);
758 for id in &ids {
759 if let Some(list) = live_jn.get(id) {
760 child_ids.extend(list.iter().copied());
761 }
762 }
763 }
764 child_ids.sort();
765 child_ids.dedup();
766 if !child_ids.is_empty() {
767 repository_factory::write::create_dto_repository(self.transaction)?
768 .restore_subtree(event_buffer, snap, &child_ids, visited)?;
769 }
770 }
771 {
772 let mut child_ids: Vec<EntityId> = Vec::new();
773 for id in to_create.iter().chain(to_update.iter()) {
774 if let Some(list) = snap.jn_dto_from_use_case_dto_out.get(id) {
775 child_ids.extend(list.iter().copied());
776 }
777 }
778 {
779 let live_jn = read_or_recover(&store.jn_dto_from_use_case_dto_out);
780 for id in &ids {
781 if let Some(list) = live_jn.get(id) {
782 child_ids.extend(list.iter().copied());
783 }
784 }
785 }
786 child_ids.sort();
787 child_ids.dedup();
788 if !child_ids.is_empty() {
789 repository_factory::write::create_dto_repository(self.transaction)?
790 .restore_subtree(event_buffer, snap, &child_ids, visited)?;
791 }
792 }
793
794 {
796 let mut live = write_or_recover(&store.use_cases);
797 for id in to_create.iter().chain(to_update.iter()) {
798 if let Some(row) = snap.use_cases.get(id) {
799 live.insert(*id, row.clone());
800 }
801 }
802 for id in &to_delete {
803 live.remove(id);
804 }
805 }
806
807 {
810 let mut live_jn = write_or_recover(&store.jn_dto_from_use_case_dto_in);
811 for id in to_create.iter().chain(to_update.iter()) {
812 match snap.jn_dto_from_use_case_dto_in.get(id) {
813 Some(v) => {
814 live_jn.insert(*id, v.clone());
815 }
816 None => {
817 live_jn.remove(id);
818 }
819 }
820 }
821 for id in &to_delete {
822 live_jn.remove(id);
823 }
824 }
825 {
826 let mut live_jn = write_or_recover(&store.jn_dto_from_use_case_dto_out);
827 for id in to_create.iter().chain(to_update.iter()) {
828 match snap.jn_dto_from_use_case_dto_out.get(id) {
829 Some(v) => {
830 live_jn.insert(*id, v.clone());
831 }
832 None => {
833 live_jn.remove(id);
834 }
835 }
836 }
837 for id in &to_delete {
838 live_jn.remove(id);
839 }
840 }
841 {
842 let mut live_jn = write_or_recover(&store.jn_entity_from_use_case_entities);
843 for id in to_create.iter().chain(to_update.iter()) {
844 match snap.jn_entity_from_use_case_entities.get(id) {
845 Some(v) => {
846 live_jn.insert(*id, v.clone());
847 }
848 None => {
849 live_jn.remove(id);
850 }
851 }
852 }
853 for id in &to_delete {
854 live_jn.remove(id);
855 }
856 }
857
858 self.reconcile_backref_file_use_case(event_buffer, snap, &ids)?;
860
861 if !to_create.is_empty() {
863 event_buffer.push(Event {
864 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Created)),
865 ids: to_create.clone(),
866 data: None,
867 });
868 event_buffer.push(Event {
869 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
870 ids: to_create.clone(),
871 data: None,
872 });
873 }
874 if !to_update.is_empty() {
875 event_buffer.push(Event {
876 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
877 ids: to_update.clone(),
878 data: None,
879 });
880 }
881 if !to_delete.is_empty() {
882 event_buffer.push(Event {
883 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Removed)),
884 ids: to_delete.clone(),
885 data: None,
886 });
887 }
888
889 Ok(())
890 }
891
892 fn reconcile_backref_file_use_case(
895 &self,
896 event_buffer: &mut EventBuffer,
897 snap: &HashMapStoreSnapshot,
898 scope_ids: &[EntityId],
899 ) -> Result<(), RepositoryError> {
900 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
901 if scope.is_empty() {
902 return Ok(());
903 }
904 let store = self.transaction.get_store();
905
906 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
908 for (left, rights) in snap.jn_use_case_from_file_use_case.iter() {
909 if rights.iter().any(|rid| scope.contains(rid)) {
910 left_keys.insert(*left);
911 }
912 }
913 {
914 let live_jn = read_or_recover(&store.jn_use_case_from_file_use_case);
915 for (left, rights) in live_jn.iter() {
916 if rights.iter().any(|rid| scope.contains(rid)) {
917 left_keys.insert(*left);
918 }
919 }
920 }
921
922 for left in left_keys {
923 let snap_list: Vec<EntityId> = snap
924 .jn_use_case_from_file_use_case
925 .get(&left)
926 .cloned()
927 .unwrap_or_default();
928 let new_list = {
929 let live_jn = read_or_recover(&store.jn_use_case_from_file_use_case);
930 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
931 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
932 &live_list, &snap_list, &scope,
933 );
934 if reconciled == live_list {
935 None
936 } else {
937 Some(reconciled)
938 }
939 };
940 if let Some(reconciled) = new_list {
941 write_or_recover(&store.jn_use_case_from_file_use_case).insert(left, reconciled);
942 event_buffer.push(Event {
943 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
944 ids: vec![left],
945 data: None,
946 });
947 }
948 }
949 Ok(())
950 }
951
952 fn reconcile_backref_feature_use_cases(
955 &self,
956 event_buffer: &mut EventBuffer,
957 snap: &HashMapStoreSnapshot,
958 scope_ids: &[EntityId],
959 ) -> Result<(), RepositoryError> {
960 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
961 if scope.is_empty() {
962 return Ok(());
963 }
964 let store = self.transaction.get_store();
965
966 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
968 for (left, rights) in snap.jn_use_case_from_feature_use_cases.iter() {
969 if rights.iter().any(|rid| scope.contains(rid)) {
970 left_keys.insert(*left);
971 }
972 }
973 {
974 let live_jn = read_or_recover(&store.jn_use_case_from_feature_use_cases);
975 for (left, rights) in live_jn.iter() {
976 if rights.iter().any(|rid| scope.contains(rid)) {
977 left_keys.insert(*left);
978 }
979 }
980 }
981
982 for left in left_keys {
983 let snap_list: Vec<EntityId> = snap
984 .jn_use_case_from_feature_use_cases
985 .get(&left)
986 .cloned()
987 .unwrap_or_default();
988 let new_list = {
989 let live_jn = read_or_recover(&store.jn_use_case_from_feature_use_cases);
990 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
991 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
992 &live_list, &snap_list, &scope,
993 );
994 if reconciled == live_list {
995 None
996 } else {
997 Some(reconciled)
998 }
999 };
1000 if let Some(reconciled) = new_list {
1001 write_or_recover(&store.jn_use_case_from_feature_use_cases)
1002 .insert(left, reconciled);
1003 event_buffer.push(Event {
1004 origin: Origin::DirectAccess(DirectAccessEntity::Feature(EntityEvent::Updated)),
1005 ids: vec![left],
1006 data: None,
1007 });
1008 }
1009 }
1010 Ok(())
1011 }
1012}
1013
1014pub struct UseCaseRepositoryRO<'a> {
1015 table: Box<dyn UseCaseTableRO + 'a>,
1016}
1017impl<'a> UseCaseRepositoryRO<'a> {
1018 pub fn new(table: Box<dyn UseCaseTableRO + 'a>) -> Self {
1019 UseCaseRepositoryRO { table }
1020 }
1021 pub fn get(&self, id: &EntityId) -> Result<Option<UseCase>, RepositoryError> {
1022 self.table.get(id)
1023 }
1024 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<UseCase>>, RepositoryError> {
1025 self.table.get_multi(ids)
1026 }
1027 pub fn get_all(&self) -> Result<Vec<UseCase>, RepositoryError> {
1028 self.table.get_all()
1029 }
1030 pub fn get_relationship(
1031 &self,
1032 id: &EntityId,
1033 field: &UseCaseRelationshipField,
1034 ) -> Result<Vec<EntityId>, RepositoryError> {
1035 self.table.get_relationship(id, field)
1036 }
1037 pub fn get_relationship_many(
1038 &self,
1039 ids: &[EntityId],
1040 field: &UseCaseRelationshipField,
1041 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
1042 self.table.get_relationship_many(ids, field)
1043 }
1044 pub fn get_relationship_count(
1045 &self,
1046 id: &EntityId,
1047 field: &UseCaseRelationshipField,
1048 ) -> Result<usize, RepositoryError> {
1049 self.table.get_relationship_count(id, field)
1050 }
1051 pub fn get_relationship_in_range(
1052 &self,
1053 id: &EntityId,
1054 field: &UseCaseRelationshipField,
1055 offset: usize,
1056 limit: usize,
1057 ) -> Result<Vec<EntityId>, RepositoryError> {
1058 self.table
1059 .get_relationship_in_range(id, field, offset, limit)
1060 }
1061 pub fn get_relationships_from_right_ids(
1062 &self,
1063 field: &UseCaseRelationshipField,
1064 right_ids: &[EntityId],
1065 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
1066 self.table
1067 .get_relationships_from_right_ids(field, right_ids)
1068 }
1069}