1use std::fmt::Display;
4
5use crate::{
6 database::transactions::Transaction,
7 direct_access::repository_factory,
8 entities::Root,
9 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10 snapshot::EntityTreeSnapshot,
11 types::EntityId,
12};
13
14use crate::error::RepositoryError;
15use serde::{Deserialize, Serialize};
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18pub enum RootRelationshipField {
19 Document,
20}
21
22impl Display for RootRelationshipField {
23 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
24 write!(f, "{:?}", self)
25 }
26}
27
28pub trait RootTable {
29 fn create(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
30 fn create_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError>;
31 fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError>;
32 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError>;
33 fn get_all(&self) -> Result<Vec<Root>, RepositoryError>;
34 fn update(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
35 fn update_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError>;
36 fn update_with_relationships(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
37 fn update_with_relationships_multi(
38 &mut self,
39 entities: &[Root],
40 ) -> Result<Vec<Root>, RepositoryError>;
41 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
42 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
43 fn get_relationship(
44 &self,
45 id: &EntityId,
46 field: &RootRelationshipField,
47 ) -> Result<Vec<EntityId>, RepositoryError>;
48 fn get_relationship_many(
49 &self,
50 ids: &[EntityId],
51 field: &RootRelationshipField,
52 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
53 fn get_relationship_count(
54 &self,
55 id: &EntityId,
56 field: &RootRelationshipField,
57 ) -> Result<usize, RepositoryError>;
58 fn get_relationship_in_range(
59 &self,
60 id: &EntityId,
61 field: &RootRelationshipField,
62 offset: usize,
63 limit: usize,
64 ) -> Result<Vec<EntityId>, RepositoryError>;
65 fn get_relationships_from_right_ids(
66 &self,
67 field: &RootRelationshipField,
68 right_ids: &[EntityId],
69 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
70 fn set_relationship_multi(
71 &mut self,
72 field: &RootRelationshipField,
73 relationships: Vec<(EntityId, Vec<EntityId>)>,
74 ) -> Result<(), RepositoryError>;
75 fn set_relationship(
76 &mut self,
77 id: &EntityId,
78 field: &RootRelationshipField,
79 right_ids: &[EntityId],
80 ) -> Result<(), RepositoryError>;
81 fn move_relationship_ids(
82 &mut self,
83 id: &EntityId,
84 field: &RootRelationshipField,
85 ids_to_move: &[EntityId],
86 new_index: i32,
87 ) -> Result<Vec<EntityId>, RepositoryError>;
88}
89
90pub trait RootTableRO {
91 fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError>;
92 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError>;
93 fn get_all(&self) -> Result<Vec<Root>, RepositoryError>;
94 fn get_relationship(
95 &self,
96 id: &EntityId,
97 field: &RootRelationshipField,
98 ) -> Result<Vec<EntityId>, RepositoryError>;
99 fn get_relationship_many(
100 &self,
101 ids: &[EntityId],
102 field: &RootRelationshipField,
103 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
104 fn get_relationship_count(
105 &self,
106 id: &EntityId,
107 field: &RootRelationshipField,
108 ) -> Result<usize, RepositoryError>;
109 fn get_relationship_in_range(
110 &self,
111 id: &EntityId,
112 field: &RootRelationshipField,
113 offset: usize,
114 limit: usize,
115 ) -> Result<Vec<EntityId>, RepositoryError>;
116 fn get_relationships_from_right_ids(
117 &self,
118 field: &RootRelationshipField,
119 right_ids: &[EntityId],
120 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
121}
122
123pub struct RootRepository<'a> {
124 redb_table: Box<dyn RootTable + 'a>,
125 transaction: &'a Transaction,
126}
127
128impl<'a> RootRepository<'a> {
129 pub fn new(redb_table: Box<dyn RootTable + 'a>, transaction: &'a Transaction) -> Self {
130 RootRepository {
131 redb_table,
132 transaction,
133 }
134 }
135
136 pub fn create_orphan(
137 &mut self,
138 event_buffer: &mut EventBuffer,
139 entity: &Root,
140 ) -> Result<Root, RepositoryError> {
141 let new = self.redb_table.create(entity)?;
142 event_buffer.push(Event {
143 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Created)),
144 ids: vec![new.id],
145 data: None,
146 });
147 Ok(new)
148 }
149
150 pub fn create_orphan_multi(
151 &mut self,
152 event_buffer: &mut EventBuffer,
153 entities: &[Root],
154 ) -> Result<Vec<Root>, RepositoryError> {
155 let new_entities = self.redb_table.create_multi(entities)?;
156 event_buffer.push(Event {
157 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Created)),
158 ids: new_entities.iter().map(|e| e.id).collect(),
159 data: None,
160 });
161 Ok(new_entities)
162 }
163
164 pub fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
165 self.redb_table.get(id)
166 }
167 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
168 self.redb_table.get_multi(ids)
169 }
170 pub fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
171 self.redb_table.get_all()
172 }
173
174 pub fn update(
175 &mut self,
176 event_buffer: &mut EventBuffer,
177 entity: &Root,
178 ) -> Result<Root, RepositoryError> {
179 let updated = self.redb_table.update(entity)?;
180 event_buffer.push(Event {
181 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
182 ids: vec![updated.id],
183 data: None,
184 });
185 Ok(updated)
186 }
187
188 pub fn update_multi(
189 &mut self,
190 event_buffer: &mut EventBuffer,
191 entities: &[Root],
192 ) -> Result<Vec<Root>, RepositoryError> {
193 let updated = self.redb_table.update_multi(entities)?;
194 event_buffer.push(Event {
195 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
196 ids: updated.iter().map(|e| e.id).collect(),
197 data: None,
198 });
199 Ok(updated)
200 }
201
202 pub fn update_with_relationships(
203 &mut self,
204 event_buffer: &mut EventBuffer,
205 entity: &Root,
206 ) -> Result<Root, RepositoryError> {
207 let updated = self.redb_table.update_with_relationships(entity)?;
208 event_buffer.push(Event {
209 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
210 ids: vec![updated.id],
211 data: None,
212 });
213 Ok(updated)
214 }
215
216 pub fn update_with_relationships_multi(
217 &mut self,
218 event_buffer: &mut EventBuffer,
219 entities: &[Root],
220 ) -> Result<Vec<Root>, RepositoryError> {
221 let updated = self.redb_table.update_with_relationships_multi(entities)?;
222 event_buffer.push(Event {
223 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
224 ids: updated.iter().map(|e| e.id).collect(),
225 data: None,
226 });
227 Ok(updated)
228 }
229
230 pub fn remove(
231 &mut self,
232 event_buffer: &mut EventBuffer,
233 id: &EntityId,
234 ) -> Result<(), RepositoryError> {
235 let entity = match self.redb_table.get(id)? {
236 Some(e) => e,
237 None => return Ok(()),
238 };
239 let document = entity.document;
242
243 repository_factory::write::create_document_repository(self.transaction)
246 .remove(event_buffer, &document)?;
247
248 self.redb_table.remove(id)?;
250 event_buffer.push(Event {
251 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Removed)),
252 ids: vec![*id],
253 data: None,
254 });
255
256 Ok(())
257 }
258
259 pub fn remove_multi(
260 &mut self,
261 event_buffer: &mut EventBuffer,
262 ids: &[EntityId],
263 ) -> Result<(), RepositoryError> {
264 let entities = self.redb_table.get_multi(ids)?;
265 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
266 return Ok(());
267 }
268
269 let document_ids: Vec<EntityId> = entities
272 .iter()
273 .filter_map(|entity| entity.as_ref().map(|entity| entity.document))
274 .collect();
275
276 repository_factory::write::create_document_repository(self.transaction)
279 .remove_multi(event_buffer, &document_ids)?;
280
281 self.redb_table.remove_multi(ids)?;
282 event_buffer.push(Event {
283 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Removed)),
284 ids: ids.into(),
285 data: None,
286 });
287
288 Ok(())
289 }
290 pub fn get_relationship(
291 &self,
292 id: &EntityId,
293 field: &RootRelationshipField,
294 ) -> Result<Vec<EntityId>, RepositoryError> {
295 self.redb_table.get_relationship(id, field)
296 }
297 pub fn get_relationship_many(
298 &self,
299 ids: &[EntityId],
300 field: &RootRelationshipField,
301 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
302 self.redb_table.get_relationship_many(ids, field)
303 }
304 pub fn get_relationship_count(
305 &self,
306 id: &EntityId,
307 field: &RootRelationshipField,
308 ) -> Result<usize, RepositoryError> {
309 self.redb_table.get_relationship_count(id, field)
310 }
311 pub fn get_relationship_in_range(
312 &self,
313 id: &EntityId,
314 field: &RootRelationshipField,
315 offset: usize,
316 limit: usize,
317 ) -> Result<Vec<EntityId>, RepositoryError> {
318 self.redb_table
319 .get_relationship_in_range(id, field, offset, limit)
320 }
321 pub fn get_relationships_from_right_ids(
322 &self,
323 field: &RootRelationshipField,
324 right_ids: &[EntityId],
325 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
326 self.redb_table
327 .get_relationships_from_right_ids(field, right_ids)
328 }
329
330 pub fn set_relationship_multi(
331 &mut self,
332 event_buffer: &mut EventBuffer,
333 field: &RootRelationshipField,
334 relationships: Vec<(EntityId, Vec<EntityId>)>,
335 ) -> Result<(), RepositoryError> {
336 let all_right_ids: Vec<EntityId> = relationships
338 .iter()
339 .flat_map(|(_, ids)| ids.iter().copied())
340 .collect();
341 if !all_right_ids.is_empty() {
342 match field {
343 RootRelationshipField::Document => {
344 let child_repo =
345 repository_factory::write::create_document_repository(self.transaction);
346 let found = child_repo.get_multi(&all_right_ids)?;
347 let missing: Vec<_> = all_right_ids
348 .iter()
349 .zip(found.iter())
350 .filter(|(_, entity)| entity.is_none())
351 .map(|(id, _)| *id)
352 .collect();
353 if !missing.is_empty() {
354 return Err(RepositoryError::MissingRelationshipTarget {
355 operation: "set_relationship_multi",
356 ids: missing,
357 });
358 }
359 }
360 }
361 }
362 self.redb_table
363 .set_relationship_multi(field, relationships.clone())?;
364 for (left_id, right_ids) in relationships {
365 event_buffer.push(Event {
366 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
367 ids: vec![left_id],
368 data: Some(format!(
369 "{}:{}",
370 field,
371 right_ids
372 .iter()
373 .map(|id| id.to_string())
374 .collect::<Vec<_>>()
375 .join(",")
376 )),
377 });
378 }
379 Ok(())
380 }
381
382 pub fn set_relationship(
383 &mut self,
384 event_buffer: &mut EventBuffer,
385 id: &EntityId,
386 field: &RootRelationshipField,
387 right_ids: &[EntityId],
388 ) -> Result<(), RepositoryError> {
389 if !right_ids.is_empty() {
391 match field {
392 RootRelationshipField::Document => {
393 let child_repo =
394 repository_factory::write::create_document_repository(self.transaction);
395 let found = child_repo.get_multi(right_ids)?;
396 let missing: Vec<_> = right_ids
397 .iter()
398 .zip(found.iter())
399 .filter(|(_, entity)| entity.is_none())
400 .map(|(id, _)| *id)
401 .collect();
402 if !missing.is_empty() {
403 return Err(RepositoryError::MissingRelationshipTarget {
404 operation: "set_relationship",
405 ids: missing,
406 });
407 }
408 }
409 }
410 }
411 self.redb_table.set_relationship(id, field, right_ids)?;
412 event_buffer.push(Event {
413 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
414 ids: vec![*id],
415 data: Some(format!(
416 "{}:{}",
417 field,
418 right_ids
419 .iter()
420 .map(|id| id.to_string())
421 .collect::<Vec<_>>()
422 .join(",")
423 )),
424 });
425 Ok(())
426 }
427
428 pub fn move_relationship_ids(
429 &mut self,
430 event_buffer: &mut EventBuffer,
431 id: &EntityId,
432 field: &RootRelationshipField,
433 ids_to_move: &[EntityId],
434 new_index: i32,
435 ) -> Result<Vec<EntityId>, RepositoryError> {
436 let reordered = self
437 .redb_table
438 .move_relationship_ids(id, field, ids_to_move, new_index)?;
439 event_buffer.push(Event {
440 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
441 ids: vec![*id],
442 data: Some(format!(
443 "{}:{}",
444 field,
445 reordered
446 .iter()
447 .map(|id| id.to_string())
448 .collect::<Vec<_>>()
449 .join(",")
450 )),
451 });
452 Ok(reordered)
453 }
454
455 pub fn snapshot(&self, _ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
456 let store_snap = self.transaction.snapshot_store();
457 Ok(EntityTreeSnapshot {
458 store_snapshot: Some(store_snap),
459 })
460 }
461
462 pub fn restore(
463 &mut self,
464 event_buffer: &mut EventBuffer,
465 snap: &EntityTreeSnapshot,
466 ) -> Result<(), RepositoryError> {
467 let store_snap = snap
468 .store_snapshot
469 .as_ref()
470 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
471 self.transaction.restore_store(store_snap);
472
473 let store = self.transaction.get_store();
474
475 let mut emit = |entity: DirectAccessEntity, ids: Vec<EntityId>| {
476 if !ids.is_empty() {
477 event_buffer.push(Event {
478 origin: Origin::DirectAccess(entity),
479 ids,
480 data: None,
481 });
482 }
483 };
484
485 let root_ids: Vec<_> = store.roots.read().unwrap().keys().copied().collect();
487 emit(
488 DirectAccessEntity::Root(EntityEvent::Created),
489 root_ids.clone(),
490 );
491 emit(DirectAccessEntity::Root(EntityEvent::Updated), root_ids);
492
493 let doc_ids: Vec<_> = store.documents.read().unwrap().keys().copied().collect();
495 emit(
496 DirectAccessEntity::Document(EntityEvent::Created),
497 doc_ids.clone(),
498 );
499 emit(DirectAccessEntity::Document(EntityEvent::Updated), doc_ids);
500
501 let frame_ids: Vec<_> = store.frames.read().unwrap().keys().copied().collect();
503 emit(
504 DirectAccessEntity::Frame(EntityEvent::Created),
505 frame_ids.clone(),
506 );
507 emit(DirectAccessEntity::Frame(EntityEvent::Updated), frame_ids);
508
509 let block_ids: Vec<_> = store.blocks.read().unwrap().keys().copied().collect();
511 emit(
512 DirectAccessEntity::Block(EntityEvent::Created),
513 block_ids.clone(),
514 );
515 emit(DirectAccessEntity::Block(EntityEvent::Updated), block_ids);
516
517 let elem_ids: Vec<_> = store
519 .inline_elements
520 .read()
521 .unwrap()
522 .keys()
523 .copied()
524 .collect();
525 emit(
526 DirectAccessEntity::InlineElement(EntityEvent::Created),
527 elem_ids,
528 );
529
530 let list_ids: Vec<_> = store.lists.read().unwrap().keys().copied().collect();
532 emit(DirectAccessEntity::List(EntityEvent::Created), list_ids);
533
534 let res_ids: Vec<_> = store.resources.read().unwrap().keys().copied().collect();
536 emit(DirectAccessEntity::Resource(EntityEvent::Created), res_ids);
537
538 let table_ids: Vec<_> = store.tables.read().unwrap().keys().copied().collect();
540 emit(
541 DirectAccessEntity::Table(EntityEvent::Created),
542 table_ids.clone(),
543 );
544 emit(DirectAccessEntity::Table(EntityEvent::Updated), table_ids);
545
546 let tc_ids: Vec<_> = store.table_cells.read().unwrap().keys().copied().collect();
548 emit(
549 DirectAccessEntity::TableCell(EntityEvent::Created),
550 tc_ids.clone(),
551 );
552 emit(DirectAccessEntity::TableCell(EntityEvent::Updated), tc_ids);
553
554 Ok(())
555 }
556}
557
558pub struct RootRepositoryRO<'a> {
559 redb_table: Box<dyn RootTableRO + 'a>,
560}
561impl<'a> RootRepositoryRO<'a> {
562 pub fn new(redb_table: Box<dyn RootTableRO + 'a>) -> Self {
563 RootRepositoryRO { redb_table }
564 }
565 pub fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
566 self.redb_table.get(id)
567 }
568 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
569 self.redb_table.get_multi(ids)
570 }
571 pub fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
572 self.redb_table.get_all()
573 }
574 pub fn get_relationship(
575 &self,
576 id: &EntityId,
577 field: &RootRelationshipField,
578 ) -> Result<Vec<EntityId>, RepositoryError> {
579 self.redb_table.get_relationship(id, field)
580 }
581 pub fn get_relationship_many(
582 &self,
583 ids: &[EntityId],
584 field: &RootRelationshipField,
585 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
586 self.redb_table.get_relationship_many(ids, field)
587 }
588 pub fn get_relationship_count(
589 &self,
590 id: &EntityId,
591 field: &RootRelationshipField,
592 ) -> Result<usize, RepositoryError> {
593 self.redb_table.get_relationship_count(id, field)
594 }
595 pub fn get_relationship_in_range(
596 &self,
597 id: &EntityId,
598 field: &RootRelationshipField,
599 offset: usize,
600 limit: usize,
601 ) -> Result<Vec<EntityId>, RepositoryError> {
602 self.redb_table
603 .get_relationship_in_range(id, field, offset, limit)
604 }
605 pub fn get_relationships_from_right_ids(
606 &self,
607 field: &RootRelationshipField,
608 right_ids: &[EntityId],
609 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
610 self.redb_table
611 .get_relationships_from_right_ids(field, right_ids)
612 }
613}