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::UserInterface,
16 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
17 snapshot::EntityTreeSnapshot,
18 types::EntityId,
19};
20
21use crate::direct_access::workspace::WorkspaceRelationshipField;
22use crate::error::RepositoryError;
23use serde::{Deserialize, Serialize};
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub enum UserInterfaceRelationshipField {}
27
28impl Display for UserInterfaceRelationshipField {
29 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
30 write!(f, "{:?}", self)
31 }
32}
33
34pub trait UserInterfaceTable {
35 fn create(&mut self, entity: &UserInterface) -> Result<UserInterface, RepositoryError>;
36 fn create_multi(
37 &mut self,
38 entities: &[UserInterface],
39 ) -> Result<Vec<UserInterface>, RepositoryError>;
40 fn get(&self, id: &EntityId) -> Result<Option<UserInterface>, RepositoryError>;
41 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<UserInterface>>, RepositoryError>;
42 fn get_all(&self) -> Result<Vec<UserInterface>, RepositoryError>;
43 fn update(&mut self, entity: &UserInterface) -> Result<UserInterface, RepositoryError>;
44 fn update_multi(
45 &mut self,
46 entities: &[UserInterface],
47 ) -> Result<Vec<UserInterface>, RepositoryError>;
48 fn update_with_relationships(
49 &mut self,
50 entity: &UserInterface,
51 ) -> Result<UserInterface, RepositoryError>;
52 fn update_with_relationships_multi(
53 &mut self,
54 entities: &[UserInterface],
55 ) -> Result<Vec<UserInterface>, RepositoryError>;
56 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
57 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
58}
59
60pub trait UserInterfaceTableRO {
61 fn get(&self, id: &EntityId) -> Result<Option<UserInterface>, RepositoryError>;
62 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<UserInterface>>, RepositoryError>;
63 fn get_all(&self) -> Result<Vec<UserInterface>, RepositoryError>;
64}
65
66pub struct UserInterfaceRepository<'a> {
67 table: Box<dyn UserInterfaceTable + 'a>,
68 transaction: &'a Transaction,
69}
70
71impl<'a> UserInterfaceRepository<'a> {
72 pub fn new(table: Box<dyn UserInterfaceTable + 'a>, transaction: &'a Transaction) -> Self {
73 UserInterfaceRepository { table, transaction }
74 }
75
76 pub fn create_orphan(
77 &mut self,
78 event_buffer: &mut EventBuffer,
79 entity: &UserInterface,
80 ) -> Result<UserInterface, RepositoryError> {
81 let new = self.table.create(entity)?;
82 event_buffer.push(Event {
83 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Created)),
84 ids: vec![new.id],
85 data: None,
86 });
87 Ok(new)
88 }
89
90 pub fn create_orphan_multi(
91 &mut self,
92 event_buffer: &mut EventBuffer,
93 entities: &[UserInterface],
94 ) -> Result<Vec<UserInterface>, RepositoryError> {
95 let new_entities = self.table.create_multi(entities)?;
96 event_buffer.push(Event {
97 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Created)),
98 ids: new_entities.iter().map(|e| e.id).collect(),
99 data: None,
100 });
101 Ok(new_entities)
102 }
103 pub fn create(
104 &mut self,
105 event_buffer: &mut EventBuffer,
106 entity: &UserInterface,
107 owner_id: EntityId,
108 _index: i32,
109 ) -> Result<UserInterface, RepositoryError> {
110 let new = self.table.create(entity)?;
111 let created_id = new.id;
112
113 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
114 if relationship_ids.is_empty() {
115 relationship_ids = vec![created_id];
116 } else {
117 self.remove_multi(event_buffer, &relationship_ids)?;
119 relationship_ids = vec![created_id];
120 }
121
122 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
123 event_buffer.push(Event {
124 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Created)),
125 ids: vec![created_id],
126 data: None,
127 });
128 Ok(new)
129 }
130
131 pub fn create_multi(
132 &mut self,
133 event_buffer: &mut EventBuffer,
134 entities: &[UserInterface],
135 owner_id: EntityId,
136 _index: i32,
137 ) -> Result<Vec<UserInterface>, RepositoryError> {
138 let new_entities = self.table.create_multi(entities)?;
139 let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
140
141 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
142 if relationship_ids.is_empty() {
143 relationship_ids = created_ids.clone();
144 } else {
145 self.remove_multi(event_buffer, &relationship_ids)?;
146 relationship_ids = created_ids.clone();
147 }
148
149 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
150 event_buffer.push(Event {
151 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Created)),
152 ids: created_ids,
153 data: None,
154 });
155 Ok(new_entities)
156 }
157
158 pub fn get(&self, id: &EntityId) -> Result<Option<UserInterface>, RepositoryError> {
159 self.table.get(id)
160 }
161 pub fn get_multi(
162 &self,
163 ids: &[EntityId],
164 ) -> Result<Vec<Option<UserInterface>>, RepositoryError> {
165 self.table.get_multi(ids)
166 }
167 pub fn get_all(&self) -> Result<Vec<UserInterface>, RepositoryError> {
168 self.table.get_all()
169 }
170
171 pub fn update(
172 &mut self,
173 event_buffer: &mut EventBuffer,
174 entity: &UserInterface,
175 ) -> Result<UserInterface, RepositoryError> {
176 let updated = self.table.update(entity)?;
177 event_buffer.push(Event {
178 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Updated)),
179 ids: vec![updated.id],
180 data: None,
181 });
182 Ok(updated)
183 }
184
185 pub fn update_multi(
186 &mut self,
187 event_buffer: &mut EventBuffer,
188 entities: &[UserInterface],
189 ) -> Result<Vec<UserInterface>, RepositoryError> {
190 let updated = self.table.update_multi(entities)?;
191 event_buffer.push(Event {
192 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Updated)),
193 ids: updated.iter().map(|e| e.id).collect(),
194 data: None,
195 });
196 Ok(updated)
197 }
198
199 pub fn update_with_relationships(
200 &mut self,
201 event_buffer: &mut EventBuffer,
202 entity: &UserInterface,
203 ) -> Result<UserInterface, RepositoryError> {
204 let updated = self.table.update_with_relationships(entity)?;
205 event_buffer.push(Event {
206 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Updated)),
207 ids: vec![updated.id],
208 data: None,
209 });
210 Ok(updated)
211 }
212
213 pub fn update_with_relationships_multi(
214 &mut self,
215 event_buffer: &mut EventBuffer,
216 entities: &[UserInterface],
217 ) -> Result<Vec<UserInterface>, RepositoryError> {
218 let updated = self.table.update_with_relationships_multi(entities)?;
219 event_buffer.push(Event {
220 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Updated)),
221 ids: updated.iter().map(|e| e.id).collect(),
222 data: None,
223 });
224 Ok(updated)
225 }
226
227 pub fn remove(
228 &mut self,
229 event_buffer: &mut EventBuffer,
230 id: &EntityId,
231 ) -> Result<(), RepositoryError> {
232 let _entity = match self.table.get(id)? {
233 Some(e) => e,
234 None => return Ok(()),
235 };
236 let affected_owner_ids: Vec<EntityId> = {
242 let owner_repo =
243 repository_factory::write::create_workspace_repository(self.transaction)?;
244 owner_repo
245 .get_relationships_from_right_ids(
246 &WorkspaceRelationshipField::UserInterface,
247 &[*id],
248 )?
249 .into_iter()
250 .map(|(owner_id, _)| owner_id)
251 .collect()
252 };
253 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
255 std::collections::HashMap::new();
256 for owner_id in &affected_owner_ids {
257 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
258 }
259
260 self.table.remove(id)?;
262 event_buffer.push(Event {
263 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Removed)),
264 ids: vec![*id],
265 data: None,
266 });
267 for owner_id in &affected_owner_ids {
269 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
270 let updated: Vec<EntityId> =
271 rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
272 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
273 }
274 }
275
276 Ok(())
277 }
278
279 pub fn remove_multi(
280 &mut self,
281 event_buffer: &mut EventBuffer,
282 ids: &[EntityId],
283 ) -> Result<(), RepositoryError> {
284 let entities = self.table.get_multi(ids)?;
285 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
286 return Ok(());
287 }
288
289 let affected_owner_ids: Vec<EntityId> = {
295 let owner_repo =
296 repository_factory::write::create_workspace_repository(self.transaction)?;
297 owner_repo
298 .get_relationships_from_right_ids(&WorkspaceRelationshipField::UserInterface, ids)?
299 .into_iter()
300 .map(|(owner_id, _)| owner_id)
301 .collect()
302 };
303 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
305 std::collections::HashMap::new();
306 for owner_id in &affected_owner_ids {
307 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
308 }
309
310 self.table.remove_multi(ids)?;
311 event_buffer.push(Event {
312 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(EntityEvent::Removed)),
313 ids: ids.into(),
314 data: None,
315 });
316 {
318 let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
319 for owner_id in &affected_owner_ids {
320 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
321 let updated: Vec<EntityId> = rel_ids
322 .iter()
323 .copied()
324 .filter(|rid| !removed_set.contains(rid))
325 .collect();
326 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
327 }
328 }
329 }
330
331 Ok(())
332 }
333 pub fn get_relationships_from_owner(
334 &self,
335 owner_id: &EntityId,
336 ) -> Result<Vec<EntityId>, RepositoryError> {
337 let repo = repository_factory::write::create_workspace_repository(self.transaction)?;
338 repo.get_relationship(owner_id, &WorkspaceRelationshipField::UserInterface)
339 }
340
341 pub fn set_relationships_in_owner(
342 &mut self,
343 event_buffer: &mut EventBuffer,
344 owner_id: &EntityId,
345 ids: &[EntityId],
346 ) -> Result<(), RepositoryError> {
347 let mut repo = repository_factory::write::create_workspace_repository(self.transaction)?;
348 repo.set_relationship(
349 event_buffer,
350 owner_id,
351 &WorkspaceRelationshipField::UserInterface,
352 ids,
353 )
354 }
355
356 pub fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
357 let store_snap = self.transaction.snapshot_store();
359 Ok(EntityTreeSnapshot {
360 store_snapshot: Some(store_snap),
361 root_ids: ids.to_vec(),
362 })
363 }
364
365 pub fn restore(
366 &mut self,
367 event_buffer: &mut EventBuffer,
368 snap: &EntityTreeSnapshot,
369 ) -> Result<(), RepositoryError> {
370 let store_snap = snap
371 .store_snapshot
372 .as_ref()
373 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
374 let snap_store = store_snap
375 .downcast_ref::<HashMapStoreSnapshot>()
376 .ok_or_else(|| RepositoryError::Serialization("snapshot type mismatch".into()))?;
377
378 let mut visited = std::collections::HashSet::new();
381 self.restore_subtree(event_buffer, snap_store, &snap.root_ids, &mut visited)?;
382
383 self.reconcile_backref_workspace_user_interface(event_buffer, snap_store, &snap.root_ids)?;
386
387 Ok(())
388 }
389
390 pub(crate) fn restore_subtree(
395 &self,
396 event_buffer: &mut EventBuffer,
397 snap: &HashMapStoreSnapshot,
398 ids: &[EntityId],
399 visited: &mut std::collections::HashSet<(&'static str, EntityId)>,
402 ) -> Result<(), RepositoryError> {
403 let ids: Vec<EntityId> = ids
404 .iter()
405 .copied()
406 .filter(|id| visited.insert(("user_interface", *id)))
407 .collect();
408 if ids.is_empty() {
409 return Ok(());
410 }
411
412 let store = self.transaction.get_store();
413
414 let mut to_create: Vec<EntityId> = Vec::new(); let mut to_update: Vec<EntityId> = Vec::new(); let mut to_delete: Vec<EntityId> = Vec::new(); {
419 let live = read_or_recover(&store.user_interfaces);
420 for id in &ids {
421 match (snap.user_interfaces.contains_key(id), live.contains_key(id)) {
422 (true, false) => to_create.push(*id),
423 (true, true) => to_update.push(*id),
424 (false, true) => to_delete.push(*id),
425 (false, false) => {}
426 }
427 }
428 }
429
430 {
435 let mut live = write_or_recover(&store.user_interfaces);
436 for id in to_create.iter().chain(to_update.iter()) {
437 if let Some(row) = snap.user_interfaces.get(id) {
438 live.insert(*id, row.clone());
439 }
440 }
441 for id in &to_delete {
442 live.remove(id);
443 }
444 }
445
446 if !to_create.is_empty() {
453 event_buffer.push(Event {
454 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(
455 EntityEvent::Created,
456 )),
457 ids: to_create.clone(),
458 data: None,
459 });
460 }
461 if !to_update.is_empty() {
462 event_buffer.push(Event {
463 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(
464 EntityEvent::Updated,
465 )),
466 ids: to_update.clone(),
467 data: None,
468 });
469 }
470 if !to_delete.is_empty() {
471 event_buffer.push(Event {
472 origin: Origin::DirectAccess(DirectAccessEntity::UserInterface(
473 EntityEvent::Removed,
474 )),
475 ids: to_delete.clone(),
476 data: None,
477 });
478 }
479
480 Ok(())
481 }
482
483 fn reconcile_backref_workspace_user_interface(
486 &self,
487 event_buffer: &mut EventBuffer,
488 snap: &HashMapStoreSnapshot,
489 scope_ids: &[EntityId],
490 ) -> Result<(), RepositoryError> {
491 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
492 if scope.is_empty() {
493 return Ok(());
494 }
495 let store = self.transaction.get_store();
496
497 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
499 for (left, rights) in snap.jn_user_interface_from_workspace_user_interface.iter() {
500 if rights.iter().any(|rid| scope.contains(rid)) {
501 left_keys.insert(*left);
502 }
503 }
504 {
505 let live_jn = read_or_recover(&store.jn_user_interface_from_workspace_user_interface);
506 for (left, rights) in live_jn.iter() {
507 if rights.iter().any(|rid| scope.contains(rid)) {
508 left_keys.insert(*left);
509 }
510 }
511 }
512
513 for left in left_keys {
514 let snap_list: Vec<EntityId> = snap
515 .jn_user_interface_from_workspace_user_interface
516 .get(&left)
517 .cloned()
518 .unwrap_or_default();
519 let new_list = {
520 let live_jn =
521 read_or_recover(&store.jn_user_interface_from_workspace_user_interface);
522 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
523 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
524 &live_list, &snap_list, &scope,
525 );
526 if reconciled == live_list {
527 None
528 } else {
529 Some(reconciled)
530 }
531 };
532 if let Some(reconciled) = new_list {
533 write_or_recover(&store.jn_user_interface_from_workspace_user_interface)
534 .insert(left, reconciled);
535 event_buffer.push(Event {
536 origin: Origin::DirectAccess(DirectAccessEntity::Workspace(
537 EntityEvent::Updated,
538 )),
539 ids: vec![left],
540 data: None,
541 });
542 }
543 }
544 Ok(())
545 }
546}
547
548pub struct UserInterfaceRepositoryRO<'a> {
549 table: Box<dyn UserInterfaceTableRO + 'a>,
550}
551impl<'a> UserInterfaceRepositoryRO<'a> {
552 pub fn new(table: Box<dyn UserInterfaceTableRO + 'a>) -> Self {
553 UserInterfaceRepositoryRO { table }
554 }
555 pub fn get(&self, id: &EntityId) -> Result<Option<UserInterface>, RepositoryError> {
556 self.table.get(id)
557 }
558 pub fn get_multi(
559 &self,
560 ids: &[EntityId],
561 ) -> Result<Vec<Option<UserInterface>>, RepositoryError> {
562 self.table.get_multi(ids)
563 }
564 pub fn get_all(&self) -> Result<Vec<UserInterface>, RepositoryError> {
565 self.table.get_all()
566 }
567}