Skip to main content

common/direct_access/workspace/
workspace_repository.rs

1// Generated by Qleany v1.7.0 from common_entity_repository.tera
2
3use std::fmt::Display;
4
5use crate::{
6    database::transactions::Transaction,
7    direct_access::repository_factory,
8    entities::Workspace,
9    event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10    snapshot::EntityTreeSnapshot,
11    types::EntityId,
12};
13
14use crate::direct_access::root::RootRelationshipField;
15use crate::error::RepositoryError;
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum WorkspaceRelationshipField {
20    Entities,
21    Features,
22    Global,
23    UserInterface,
24}
25
26impl Display for WorkspaceRelationshipField {
27    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
28        write!(f, "{:?}", self)
29    }
30}
31
32pub trait WorkspaceTable {
33    fn create(&mut self, entity: &Workspace) -> Result<Workspace, RepositoryError>;
34    fn create_multi(&mut self, entities: &[Workspace]) -> Result<Vec<Workspace>, RepositoryError>;
35    fn get(&self, id: &EntityId) -> Result<Option<Workspace>, RepositoryError>;
36    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Workspace>>, RepositoryError>;
37    fn get_all(&self) -> Result<Vec<Workspace>, RepositoryError>;
38    fn update(&mut self, entity: &Workspace) -> Result<Workspace, RepositoryError>;
39    fn update_multi(&mut self, entities: &[Workspace]) -> Result<Vec<Workspace>, RepositoryError>;
40    fn update_with_relationships(
41        &mut self,
42        entity: &Workspace,
43    ) -> Result<Workspace, RepositoryError>;
44    fn update_with_relationships_multi(
45        &mut self,
46        entities: &[Workspace],
47    ) -> Result<Vec<Workspace>, RepositoryError>;
48    fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
49    fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
50    fn get_relationship(
51        &self,
52        id: &EntityId,
53        field: &WorkspaceRelationshipField,
54    ) -> Result<Vec<EntityId>, RepositoryError>;
55    fn get_relationship_many(
56        &self,
57        ids: &[EntityId],
58        field: &WorkspaceRelationshipField,
59    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
60    fn get_relationship_count(
61        &self,
62        id: &EntityId,
63        field: &WorkspaceRelationshipField,
64    ) -> Result<usize, RepositoryError>;
65    fn get_relationship_in_range(
66        &self,
67        id: &EntityId,
68        field: &WorkspaceRelationshipField,
69        offset: usize,
70        limit: usize,
71    ) -> Result<Vec<EntityId>, RepositoryError>;
72    fn get_relationships_from_right_ids(
73        &self,
74        field: &WorkspaceRelationshipField,
75        right_ids: &[EntityId],
76    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
77    fn set_relationship_multi(
78        &mut self,
79        field: &WorkspaceRelationshipField,
80        relationships: Vec<(EntityId, Vec<EntityId>)>,
81    ) -> Result<(), RepositoryError>;
82    fn set_relationship(
83        &mut self,
84        id: &EntityId,
85        field: &WorkspaceRelationshipField,
86        right_ids: &[EntityId],
87    ) -> Result<(), RepositoryError>;
88    fn move_relationship_ids(
89        &mut self,
90        id: &EntityId,
91        field: &WorkspaceRelationshipField,
92        ids_to_move: &[EntityId],
93        new_index: i32,
94    ) -> Result<Vec<EntityId>, RepositoryError>;
95}
96
97pub trait WorkspaceTableRO {
98    fn get(&self, id: &EntityId) -> Result<Option<Workspace>, RepositoryError>;
99    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Workspace>>, RepositoryError>;
100    fn get_all(&self) -> Result<Vec<Workspace>, RepositoryError>;
101    fn get_relationship(
102        &self,
103        id: &EntityId,
104        field: &WorkspaceRelationshipField,
105    ) -> Result<Vec<EntityId>, RepositoryError>;
106    fn get_relationship_many(
107        &self,
108        ids: &[EntityId],
109        field: &WorkspaceRelationshipField,
110    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
111    fn get_relationship_count(
112        &self,
113        id: &EntityId,
114        field: &WorkspaceRelationshipField,
115    ) -> Result<usize, RepositoryError>;
116    fn get_relationship_in_range(
117        &self,
118        id: &EntityId,
119        field: &WorkspaceRelationshipField,
120        offset: usize,
121        limit: usize,
122    ) -> Result<Vec<EntityId>, RepositoryError>;
123    fn get_relationships_from_right_ids(
124        &self,
125        field: &WorkspaceRelationshipField,
126        right_ids: &[EntityId],
127    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
128}
129
130pub struct WorkspaceRepository<'a> {
131    table: Box<dyn WorkspaceTable + 'a>,
132    transaction: &'a Transaction,
133}
134
135impl<'a> WorkspaceRepository<'a> {
136    pub fn new(table: Box<dyn WorkspaceTable + 'a>, transaction: &'a Transaction) -> Self {
137        WorkspaceRepository { table, transaction }
138    }
139
140    pub fn create_orphan(
141        &mut self,
142        event_buffer: &mut EventBuffer,
143        entity: &Workspace,
144    ) -> Result<Workspace, RepositoryError> {
145        let new = self.table.create(entity)?;
146        event_buffer.push(Event {
147            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Created)),
148            ids: vec![new.id],
149            data: None,
150        });
151        Ok(new)
152    }
153
154    pub fn create_orphan_multi(
155        &mut self,
156        event_buffer: &mut EventBuffer,
157        entities: &[Workspace],
158    ) -> Result<Vec<Workspace>, RepositoryError> {
159        let new_entities = self.table.create_multi(entities)?;
160        event_buffer.push(Event {
161            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Created)),
162            ids: new_entities.iter().map(|e| e.id).collect(),
163            data: None,
164        });
165        Ok(new_entities)
166    }
167    pub fn create(
168        &mut self,
169        event_buffer: &mut EventBuffer,
170        entity: &Workspace,
171        owner_id: EntityId,
172        _index: i32,
173    ) -> Result<Workspace, RepositoryError> {
174        let new = self.table.create(entity)?;
175        let created_id = new.id;
176
177        let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
178        if relationship_ids.is_empty() {
179            relationship_ids = vec![created_id];
180        } else {
181            // Replace existing relationship: cascade-remove old entities first
182            self.remove_multi(event_buffer, &relationship_ids)?;
183            relationship_ids = vec![created_id];
184        }
185
186        self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
187        event_buffer.push(Event {
188            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Created)),
189            ids: vec![created_id],
190            data: None,
191        });
192        Ok(new)
193    }
194
195    pub fn create_multi(
196        &mut self,
197        event_buffer: &mut EventBuffer,
198        entities: &[Workspace],
199        owner_id: EntityId,
200        _index: i32,
201    ) -> Result<Vec<Workspace>, RepositoryError> {
202        let new_entities = self.table.create_multi(entities)?;
203        let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
204
205        let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
206        if relationship_ids.is_empty() {
207            relationship_ids = created_ids.clone();
208        } else {
209            self.remove_multi(event_buffer, &relationship_ids)?;
210            relationship_ids = created_ids.clone();
211        }
212
213        self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
214        event_buffer.push(Event {
215            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Created)),
216            ids: created_ids,
217            data: None,
218        });
219        Ok(new_entities)
220    }
221
222    pub fn get(&self, id: &EntityId) -> Result<Option<Workspace>, RepositoryError> {
223        self.table.get(id)
224    }
225    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Workspace>>, RepositoryError> {
226        self.table.get_multi(ids)
227    }
228    pub fn get_all(&self) -> Result<Vec<Workspace>, RepositoryError> {
229        self.table.get_all()
230    }
231
232    pub fn update(
233        &mut self,
234        event_buffer: &mut EventBuffer,
235        entity: &Workspace,
236    ) -> Result<Workspace, RepositoryError> {
237        let updated = self.table.update(entity)?;
238        event_buffer.push(Event {
239            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Updated)),
240            ids: vec![updated.id],
241            data: None,
242        });
243        Ok(updated)
244    }
245
246    pub fn update_multi(
247        &mut self,
248        event_buffer: &mut EventBuffer,
249        entities: &[Workspace],
250    ) -> Result<Vec<Workspace>, RepositoryError> {
251        let updated = self.table.update_multi(entities)?;
252        event_buffer.push(Event {
253            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Updated)),
254            ids: updated.iter().map(|e| e.id).collect(),
255            data: None,
256        });
257        Ok(updated)
258    }
259
260    pub fn update_with_relationships(
261        &mut self,
262        event_buffer: &mut EventBuffer,
263        entity: &Workspace,
264    ) -> Result<Workspace, RepositoryError> {
265        let updated = self.table.update_with_relationships(entity)?;
266        event_buffer.push(Event {
267            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Updated)),
268            ids: vec![updated.id],
269            data: None,
270        });
271        Ok(updated)
272    }
273
274    pub fn update_with_relationships_multi(
275        &mut self,
276        event_buffer: &mut EventBuffer,
277        entities: &[Workspace],
278    ) -> Result<Vec<Workspace>, RepositoryError> {
279        let updated = self.table.update_with_relationships_multi(entities)?;
280        event_buffer.push(Event {
281            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Updated)),
282            ids: updated.iter().map(|e| e.id).collect(),
283            data: None,
284        });
285        Ok(updated)
286    }
287
288    pub fn remove(
289        &mut self,
290        event_buffer: &mut EventBuffer,
291        id: &EntityId,
292    ) -> Result<(), RepositoryError> {
293        let entity = match self.table.get(id)? {
294            Some(e) => e,
295            None => return Ok(()),
296        };
297        // get all strong forward relationship fields
298
299        let global = entity.global;
300        let entities = entity.entities.clone();
301        let features = entity.features.clone();
302        let user_interface = entity.user_interface;
303
304        // remove all strong relationships, initiating a cascade remove
305
306        repository_factory::write::create_global_repository(self.transaction)?
307            .remove(event_buffer, &global)?;
308        repository_factory::write::create_entity_repository(self.transaction)?
309            .remove_multi(event_buffer, &entities)?;
310        repository_factory::write::create_feature_repository(self.transaction)?
311            .remove_multi(event_buffer, &features)?;
312        repository_factory::write::create_user_interface_repository(self.transaction)?
313            .remove(event_buffer, &user_interface)?;
314        // Before removal, find which owner(s) reference this entity
315        let affected_owner_ids: Vec<EntityId> = {
316            let owner_repo = repository_factory::write::create_root_repository(self.transaction)?;
317            owner_repo
318                .get_relationships_from_right_ids(&RootRelationshipField::Workspace, &[*id])?
319                .into_iter()
320                .map(|(owner_id, _)| owner_id)
321                .collect()
322        };
323        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
324        let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
325            std::collections::HashMap::new();
326        for owner_id in &affected_owner_ids {
327            owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
328        }
329
330        // remove entity
331        self.table.remove(id)?;
332        event_buffer.push(Event {
333            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Removed)),
334            ids: vec![*id],
335            data: None,
336        });
337        // Update each affected owner's relationship to exclude removed ID (emits Updated event)
338        for owner_id in &affected_owner_ids {
339            if let Some(rel_ids) = owner_rel_before.get(owner_id) {
340                let updated: Vec<EntityId> =
341                    rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
342                self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
343            }
344        }
345
346        Ok(())
347    }
348
349    pub fn remove_multi(
350        &mut self,
351        event_buffer: &mut EventBuffer,
352        ids: &[EntityId],
353    ) -> Result<(), RepositoryError> {
354        let entities = self.table.get_multi(ids)?;
355        if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
356            return Ok(());
357        }
358
359        // get all strong forward relationship fields
360
361        let global_ids: Vec<EntityId> = entities
362            .iter()
363            .filter_map(|entity| entity.as_ref().map(|entity| entity.global))
364            .collect();
365        let mut entities_ids: Vec<EntityId> = entities
366            .iter()
367            .flat_map(|entity| entity.as_ref().map(|entity| entity.entities.clone()))
368            .flatten()
369            .collect();
370        // remove duplicates
371        entities_ids.sort();
372        entities_ids.dedup();
373        let mut features_ids: Vec<EntityId> = entities
374            .iter()
375            .flat_map(|entity| entity.as_ref().map(|entity| entity.features.clone()))
376            .flatten()
377            .collect();
378        // remove duplicates
379        features_ids.sort();
380        features_ids.dedup();
381        let user_interface_ids: Vec<EntityId> = entities
382            .iter()
383            .filter_map(|entity| entity.as_ref().map(|entity| entity.user_interface))
384            .collect();
385
386        // remove all strong relationships, initiating a cascade remove
387
388        repository_factory::write::create_global_repository(self.transaction)?
389            .remove_multi(event_buffer, &global_ids)?;
390        repository_factory::write::create_entity_repository(self.transaction)?
391            .remove_multi(event_buffer, &entities_ids)?;
392        repository_factory::write::create_feature_repository(self.transaction)?
393            .remove_multi(event_buffer, &features_ids)?;
394        repository_factory::write::create_user_interface_repository(self.transaction)?
395            .remove_multi(event_buffer, &user_interface_ids)?;
396        // Before removal, find which owner(s) reference these entities
397        let affected_owner_ids: Vec<EntityId> = {
398            let owner_repo = repository_factory::write::create_root_repository(self.transaction)?;
399            owner_repo
400                .get_relationships_from_right_ids(&RootRelationshipField::Workspace, ids)?
401                .into_iter()
402                .map(|(owner_id, _)| owner_id)
403                .collect()
404        };
405        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
406        let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
407            std::collections::HashMap::new();
408        for owner_id in &affected_owner_ids {
409            owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
410        }
411
412        self.table.remove_multi(ids)?;
413        event_buffer.push(Event {
414            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Removed)),
415            ids: ids.into(),
416            data: None,
417        });
418        // Update each affected owner's relationship to exclude removed IDs (emits Updated event)
419        {
420            let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
421            for owner_id in &affected_owner_ids {
422                if let Some(rel_ids) = owner_rel_before.get(owner_id) {
423                    let updated: Vec<EntityId> = rel_ids
424                        .iter()
425                        .copied()
426                        .filter(|rid| !removed_set.contains(rid))
427                        .collect();
428                    self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
429                }
430            }
431        }
432
433        Ok(())
434    }
435    pub fn get_relationship(
436        &self,
437        id: &EntityId,
438        field: &WorkspaceRelationshipField,
439    ) -> Result<Vec<EntityId>, RepositoryError> {
440        self.table.get_relationship(id, field)
441    }
442    pub fn get_relationship_many(
443        &self,
444        ids: &[EntityId],
445        field: &WorkspaceRelationshipField,
446    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
447        self.table.get_relationship_many(ids, field)
448    }
449    pub fn get_relationship_count(
450        &self,
451        id: &EntityId,
452        field: &WorkspaceRelationshipField,
453    ) -> Result<usize, RepositoryError> {
454        self.table.get_relationship_count(id, field)
455    }
456    pub fn get_relationship_in_range(
457        &self,
458        id: &EntityId,
459        field: &WorkspaceRelationshipField,
460        offset: usize,
461        limit: usize,
462    ) -> Result<Vec<EntityId>, RepositoryError> {
463        self.table
464            .get_relationship_in_range(id, field, offset, limit)
465    }
466    pub fn get_relationships_from_right_ids(
467        &self,
468        field: &WorkspaceRelationshipField,
469        right_ids: &[EntityId],
470    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
471        self.table
472            .get_relationships_from_right_ids(field, right_ids)
473    }
474
475    pub fn set_relationship_multi(
476        &mut self,
477        event_buffer: &mut EventBuffer,
478        field: &WorkspaceRelationshipField,
479        relationships: Vec<(EntityId, Vec<EntityId>)>,
480    ) -> Result<(), RepositoryError> {
481        // Validate that all right_ids exist
482        let all_right_ids: Vec<EntityId> = relationships
483            .iter()
484            .flat_map(|(_, ids)| ids.iter().copied())
485            .collect();
486        if !all_right_ids.is_empty() {
487            match field {
488                WorkspaceRelationshipField::Entities => {
489                    let child_repo =
490                        repository_factory::write::create_entity_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                WorkspaceRelationshipField::Features => {
506                    let child_repo =
507                        repository_factory::write::create_feature_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                WorkspaceRelationshipField::Global => {
523                    let child_repo =
524                        repository_factory::write::create_global_repository(self.transaction)?;
525                    let found = child_repo.get_multi(&all_right_ids)?;
526                    let missing: Vec<_> = all_right_ids
527                        .iter()
528                        .zip(found.iter())
529                        .filter(|(_, entity)| entity.is_none())
530                        .map(|(id, _)| *id)
531                        .collect();
532                    if !missing.is_empty() {
533                        return Err(RepositoryError::MissingRelationshipTarget {
534                            operation: "set_relationship_multi",
535                            ids: missing,
536                        });
537                    }
538                }
539                WorkspaceRelationshipField::UserInterface => {
540                    let child_repo = repository_factory::write::create_user_interface_repository(
541                        self.transaction,
542                    )?;
543                    let found = child_repo.get_multi(&all_right_ids)?;
544                    let missing: Vec<_> = all_right_ids
545                        .iter()
546                        .zip(found.iter())
547                        .filter(|(_, entity)| entity.is_none())
548                        .map(|(id, _)| *id)
549                        .collect();
550                    if !missing.is_empty() {
551                        return Err(RepositoryError::MissingRelationshipTarget {
552                            operation: "set_relationship_multi",
553                            ids: missing,
554                        });
555                    }
556                }
557            }
558        }
559        self.table
560            .set_relationship_multi(field, relationships.clone())?;
561        for (left_id, right_ids) in relationships {
562            event_buffer.push(Event {
563                origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Updated)),
564                ids: vec![left_id],
565                data: Some(format!(
566                    "{}:{}",
567                    field,
568                    right_ids
569                        .iter()
570                        .map(|id| id.to_string())
571                        .collect::<Vec<_>>()
572                        .join(",")
573                )),
574            });
575        }
576        Ok(())
577    }
578
579    pub fn set_relationship(
580        &mut self,
581        event_buffer: &mut EventBuffer,
582        id: &EntityId,
583        field: &WorkspaceRelationshipField,
584        right_ids: &[EntityId],
585    ) -> Result<(), RepositoryError> {
586        // Validate that all right_ids exist
587        if !right_ids.is_empty() {
588            match field {
589                WorkspaceRelationshipField::Entities => {
590                    let child_repo =
591                        repository_factory::write::create_entity_repository(self.transaction)?;
592                    let found = child_repo.get_multi(right_ids)?;
593                    let missing: Vec<_> = right_ids
594                        .iter()
595                        .zip(found.iter())
596                        .filter(|(_, entity)| entity.is_none())
597                        .map(|(id, _)| *id)
598                        .collect();
599                    if !missing.is_empty() {
600                        return Err(RepositoryError::MissingRelationshipTarget {
601                            operation: "set_relationship",
602                            ids: missing,
603                        });
604                    }
605                }
606                WorkspaceRelationshipField::Features => {
607                    let child_repo =
608                        repository_factory::write::create_feature_repository(self.transaction)?;
609                    let found = child_repo.get_multi(right_ids)?;
610                    let missing: Vec<_> = right_ids
611                        .iter()
612                        .zip(found.iter())
613                        .filter(|(_, entity)| entity.is_none())
614                        .map(|(id, _)| *id)
615                        .collect();
616                    if !missing.is_empty() {
617                        return Err(RepositoryError::MissingRelationshipTarget {
618                            operation: "set_relationship",
619                            ids: missing,
620                        });
621                    }
622                }
623                WorkspaceRelationshipField::Global => {
624                    let child_repo =
625                        repository_factory::write::create_global_repository(self.transaction)?;
626                    let found = child_repo.get_multi(right_ids)?;
627                    let missing: Vec<_> = right_ids
628                        .iter()
629                        .zip(found.iter())
630                        .filter(|(_, entity)| entity.is_none())
631                        .map(|(id, _)| *id)
632                        .collect();
633                    if !missing.is_empty() {
634                        return Err(RepositoryError::MissingRelationshipTarget {
635                            operation: "set_relationship",
636                            ids: missing,
637                        });
638                    }
639                }
640                WorkspaceRelationshipField::UserInterface => {
641                    let child_repo = repository_factory::write::create_user_interface_repository(
642                        self.transaction,
643                    )?;
644                    let found = child_repo.get_multi(right_ids)?;
645                    let missing: Vec<_> = right_ids
646                        .iter()
647                        .zip(found.iter())
648                        .filter(|(_, entity)| entity.is_none())
649                        .map(|(id, _)| *id)
650                        .collect();
651                    if !missing.is_empty() {
652                        return Err(RepositoryError::MissingRelationshipTarget {
653                            operation: "set_relationship",
654                            ids: missing,
655                        });
656                    }
657                }
658            }
659        }
660        self.table.set_relationship(id, field, right_ids)?;
661        event_buffer.push(Event {
662            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Updated)),
663            ids: vec![*id],
664            data: Some(format!(
665                "{}:{}",
666                field,
667                right_ids
668                    .iter()
669                    .map(|id| id.to_string())
670                    .collect::<Vec<_>>()
671                    .join(",")
672            )),
673        });
674        Ok(())
675    }
676
677    pub fn move_relationship_ids(
678        &mut self,
679        event_buffer: &mut EventBuffer,
680        id: &EntityId,
681        field: &WorkspaceRelationshipField,
682        ids_to_move: &[EntityId],
683        new_index: i32,
684    ) -> Result<Vec<EntityId>, RepositoryError> {
685        let reordered = self
686            .table
687            .move_relationship_ids(id, field, ids_to_move, new_index)?;
688        event_buffer.push(Event {
689            origin: Origin::DirectAccess(DirectAccessEntity::Workspace(EntityEvent::Updated)),
690            ids: vec![*id],
691            data: Some(format!(
692                "{}:{}",
693                field,
694                reordered
695                    .iter()
696                    .map(|id| id.to_string())
697                    .collect::<Vec<_>>()
698                    .join(",")
699            )),
700        });
701        Ok(reordered)
702    }
703    pub fn get_relationships_from_owner(
704        &self,
705        owner_id: &EntityId,
706    ) -> Result<Vec<EntityId>, RepositoryError> {
707        let repo = repository_factory::write::create_root_repository(self.transaction)?;
708        repo.get_relationship(owner_id, &RootRelationshipField::Workspace)
709    }
710
711    pub fn set_relationships_in_owner(
712        &mut self,
713        event_buffer: &mut EventBuffer,
714        owner_id: &EntityId,
715        ids: &[EntityId],
716    ) -> Result<(), RepositoryError> {
717        let mut repo = repository_factory::write::create_root_repository(self.transaction)?;
718        repo.set_relationship(
719            event_buffer,
720            owner_id,
721            &RootRelationshipField::Workspace,
722            ids,
723        )
724    }
725
726    pub fn snapshot(&self, _ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
727        let store_snap = self.transaction.snapshot_store();
728        Ok(EntityTreeSnapshot {
729            store_snapshot: Some(store_snap),
730        })
731    }
732
733    pub fn restore(
734        &mut self,
735        event_buffer: &mut EventBuffer,
736        snap: &EntityTreeSnapshot,
737    ) -> Result<(), RepositoryError> {
738        let store_snap = snap
739            .store_snapshot
740            .as_ref()
741            .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
742        self.transaction.restore_store(store_snap);
743
744        let store = self.transaction.get_store();
745
746        let mut emit = |entity: DirectAccessEntity, ids: Vec<EntityId>| {
747            if !ids.is_empty() {
748                event_buffer.push(Event {
749                    origin: Origin::DirectAccess(entity),
750                    ids,
751                    data: None,
752                });
753            }
754        };
755
756        // Emit Created events for this entity
757        let workspace_ids: Vec<_> = store.workspaces.read().unwrap().keys().copied().collect();
758        emit(
759            DirectAccessEntity::Workspace(EntityEvent::Created),
760            workspace_ids.clone(),
761        );
762        emit(
763            DirectAccessEntity::Workspace(EntityEvent::Updated),
764            workspace_ids,
765        );
766
767        // Emit Created events for strong children
768
769        {
770            let child_ids: Vec<_> = store.globals.read().unwrap().keys().copied().collect();
771            emit(
772                DirectAccessEntity::Global(EntityEvent::Created),
773                child_ids.clone(),
774            );
775        }
776        {
777            let child_ids: Vec<_> = store.entitys.read().unwrap().keys().copied().collect();
778            emit(
779                DirectAccessEntity::Entity(EntityEvent::Created),
780                child_ids.clone(),
781            );
782            emit(DirectAccessEntity::Entity(EntityEvent::Updated), child_ids);
783        }
784        {
785            let child_ids: Vec<_> = store.features.read().unwrap().keys().copied().collect();
786            emit(
787                DirectAccessEntity::Feature(EntityEvent::Created),
788                child_ids.clone(),
789            );
790            emit(DirectAccessEntity::Feature(EntityEvent::Updated), child_ids);
791        }
792        {
793            let child_ids: Vec<_> = store
794                .user_interfaces
795                .read()
796                .unwrap()
797                .keys()
798                .copied()
799                .collect();
800            emit(
801                DirectAccessEntity::UserInterface(EntityEvent::Created),
802                child_ids.clone(),
803            );
804        }
805
806        Ok(())
807    }
808}
809
810pub struct WorkspaceRepositoryRO<'a> {
811    table: Box<dyn WorkspaceTableRO + 'a>,
812}
813impl<'a> WorkspaceRepositoryRO<'a> {
814    pub fn new(table: Box<dyn WorkspaceTableRO + 'a>) -> Self {
815        WorkspaceRepositoryRO { table }
816    }
817    pub fn get(&self, id: &EntityId) -> Result<Option<Workspace>, RepositoryError> {
818        self.table.get(id)
819    }
820    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Workspace>>, RepositoryError> {
821        self.table.get_multi(ids)
822    }
823    pub fn get_all(&self) -> Result<Vec<Workspace>, RepositoryError> {
824        self.table.get_all()
825    }
826    pub fn get_relationship(
827        &self,
828        id: &EntityId,
829        field: &WorkspaceRelationshipField,
830    ) -> Result<Vec<EntityId>, RepositoryError> {
831        self.table.get_relationship(id, field)
832    }
833    pub fn get_relationship_many(
834        &self,
835        ids: &[EntityId],
836        field: &WorkspaceRelationshipField,
837    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
838        self.table.get_relationship_many(ids, field)
839    }
840    pub fn get_relationship_count(
841        &self,
842        id: &EntityId,
843        field: &WorkspaceRelationshipField,
844    ) -> Result<usize, RepositoryError> {
845        self.table.get_relationship_count(id, field)
846    }
847    pub fn get_relationship_in_range(
848        &self,
849        id: &EntityId,
850        field: &WorkspaceRelationshipField,
851        offset: usize,
852        limit: usize,
853    ) -> Result<Vec<EntityId>, RepositoryError> {
854        self.table
855            .get_relationship_in_range(id, field, offset, limit)
856    }
857    pub fn get_relationships_from_right_ids(
858        &self,
859        field: &WorkspaceRelationshipField,
860        right_ids: &[EntityId],
861    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
862        self.table
863            .get_relationships_from_right_ids(field, right_ids)
864    }
865}