1use std::fmt::Display;
4
5use crate::{
6 database::transactions::Transaction,
7 direct_access::repository_factory,
8 entities::InlineElement,
9 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10 snapshot::EntityTreeSnapshot,
11 types::EntityId,
12};
13
14use crate::direct_access::block::BlockRelationshipField;
15use crate::error::RepositoryError;
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum InlineElementRelationshipField {}
20
21impl Display for InlineElementRelationshipField {
22 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23 write!(f, "{:?}", self)
24 }
25}
26
27pub trait InlineElementTable {
28 fn create(&mut self, entity: &InlineElement) -> Result<InlineElement, RepositoryError>;
29 fn create_multi(
30 &mut self,
31 entities: &[InlineElement],
32 ) -> Result<Vec<InlineElement>, RepositoryError>;
33 fn get(&self, id: &EntityId) -> Result<Option<InlineElement>, RepositoryError>;
34 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<InlineElement>>, RepositoryError>;
35 fn get_all(&self) -> Result<Vec<InlineElement>, RepositoryError>;
36 fn update(&mut self, entity: &InlineElement) -> Result<InlineElement, RepositoryError>;
37 fn update_multi(
38 &mut self,
39 entities: &[InlineElement],
40 ) -> Result<Vec<InlineElement>, RepositoryError>;
41 fn update_with_relationships(
42 &mut self,
43 entity: &InlineElement,
44 ) -> Result<InlineElement, RepositoryError>;
45 fn update_with_relationships_multi(
46 &mut self,
47 entities: &[InlineElement],
48 ) -> Result<Vec<InlineElement>, RepositoryError>;
49 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
50 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
51}
52
53pub trait InlineElementTableRO {
54 fn get(&self, id: &EntityId) -> Result<Option<InlineElement>, RepositoryError>;
55 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<InlineElement>>, RepositoryError>;
56 fn get_all(&self) -> Result<Vec<InlineElement>, RepositoryError>;
57}
58
59pub struct InlineElementRepository<'a> {
60 redb_table: Box<dyn InlineElementTable + 'a>,
61 transaction: &'a Transaction,
62}
63
64impl<'a> InlineElementRepository<'a> {
65 pub fn new(redb_table: Box<dyn InlineElementTable + 'a>, transaction: &'a Transaction) -> Self {
66 InlineElementRepository {
67 redb_table,
68 transaction,
69 }
70 }
71
72 pub fn create_orphan(
73 &mut self,
74 event_buffer: &mut EventBuffer,
75 entity: &InlineElement,
76 ) -> Result<InlineElement, RepositoryError> {
77 let new = self.redb_table.create(entity)?;
78 event_buffer.push(Event {
79 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Created)),
80 ids: vec![new.id],
81 data: None,
82 });
83 Ok(new)
84 }
85
86 pub fn create_orphan_multi(
87 &mut self,
88 event_buffer: &mut EventBuffer,
89 entities: &[InlineElement],
90 ) -> Result<Vec<InlineElement>, RepositoryError> {
91 let new_entities = self.redb_table.create_multi(entities)?;
92 event_buffer.push(Event {
93 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Created)),
94 ids: new_entities.iter().map(|e| e.id).collect(),
95 data: None,
96 });
97 Ok(new_entities)
98 }
99 pub fn create(
100 &mut self,
101 event_buffer: &mut EventBuffer,
102 entity: &InlineElement,
103 owner_id: EntityId,
104 index: i32,
105 ) -> Result<InlineElement, RepositoryError> {
106 let new = self.redb_table.create(entity)?;
107 let created_id = new.id;
108
109 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
110 if index >= 0 && (index as usize) < relationship_ids.len() {
112 relationship_ids.insert(index as usize, created_id);
113 } else {
114 relationship_ids.push(created_id);
115 }
116
117 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
118 event_buffer.push(Event {
119 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Created)),
120 ids: vec![created_id],
121 data: None,
122 });
123 Ok(new)
124 }
125
126 pub fn create_multi(
127 &mut self,
128 event_buffer: &mut EventBuffer,
129 entities: &[InlineElement],
130 owner_id: EntityId,
131 index: i32,
132 ) -> Result<Vec<InlineElement>, RepositoryError> {
133 let new_entities = self.redb_table.create_multi(entities)?;
134 let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
135
136 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
137 if index >= 0 && (index as usize) < relationship_ids.len() {
138 for (i, id) in created_ids.iter().enumerate() {
139 relationship_ids.insert(index as usize + i, *id);
140 }
141 } else {
142 relationship_ids.extend(created_ids.iter());
143 }
144
145 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
146 event_buffer.push(Event {
147 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Created)),
148 ids: created_ids,
149 data: None,
150 });
151 Ok(new_entities)
152 }
153
154 pub fn get(&self, id: &EntityId) -> Result<Option<InlineElement>, RepositoryError> {
155 self.redb_table.get(id)
156 }
157 pub fn get_multi(
158 &self,
159 ids: &[EntityId],
160 ) -> Result<Vec<Option<InlineElement>>, RepositoryError> {
161 self.redb_table.get_multi(ids)
162 }
163 pub fn get_all(&self) -> Result<Vec<InlineElement>, RepositoryError> {
164 self.redb_table.get_all()
165 }
166
167 pub fn update(
168 &mut self,
169 event_buffer: &mut EventBuffer,
170 entity: &InlineElement,
171 ) -> Result<InlineElement, RepositoryError> {
172 let updated = self.redb_table.update(entity)?;
173 event_buffer.push(Event {
174 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Updated)),
175 ids: vec![updated.id],
176 data: None,
177 });
178 Ok(updated)
179 }
180
181 pub fn update_multi(
182 &mut self,
183 event_buffer: &mut EventBuffer,
184 entities: &[InlineElement],
185 ) -> Result<Vec<InlineElement>, RepositoryError> {
186 let updated = self.redb_table.update_multi(entities)?;
187 event_buffer.push(Event {
188 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Updated)),
189 ids: updated.iter().map(|e| e.id).collect(),
190 data: None,
191 });
192 Ok(updated)
193 }
194
195 pub fn update_with_relationships(
196 &mut self,
197 event_buffer: &mut EventBuffer,
198 entity: &InlineElement,
199 ) -> Result<InlineElement, RepositoryError> {
200 let updated = self.redb_table.update_with_relationships(entity)?;
201 event_buffer.push(Event {
202 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Updated)),
203 ids: vec![updated.id],
204 data: None,
205 });
206 Ok(updated)
207 }
208
209 pub fn update_with_relationships_multi(
210 &mut self,
211 event_buffer: &mut EventBuffer,
212 entities: &[InlineElement],
213 ) -> Result<Vec<InlineElement>, RepositoryError> {
214 let updated = self.redb_table.update_with_relationships_multi(entities)?;
215 event_buffer.push(Event {
216 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Updated)),
217 ids: updated.iter().map(|e| e.id).collect(),
218 data: None,
219 });
220 Ok(updated)
221 }
222
223 pub fn remove(
224 &mut self,
225 event_buffer: &mut EventBuffer,
226 id: &EntityId,
227 ) -> Result<(), RepositoryError> {
228 let _entity = match self.redb_table.get(id)? {
229 Some(e) => e,
230 None => return Ok(()),
231 };
232 let affected_owner_ids: Vec<EntityId> = {
238 let owner_repo = repository_factory::write::create_block_repository(self.transaction);
239 owner_repo
240 .get_relationships_from_right_ids(&BlockRelationshipField::Elements, &[*id])?
241 .into_iter()
242 .map(|(owner_id, _)| owner_id)
243 .collect()
244 };
245 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
247 std::collections::HashMap::new();
248 for owner_id in &affected_owner_ids {
249 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
250 }
251
252 self.redb_table.remove(id)?;
254 event_buffer.push(Event {
255 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Removed)),
256 ids: vec![*id],
257 data: None,
258 });
259 for owner_id in &affected_owner_ids {
261 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
262 let updated: Vec<EntityId> =
263 rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
264 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
265 }
266 }
267
268 Ok(())
269 }
270
271 pub fn remove_multi(
272 &mut self,
273 event_buffer: &mut EventBuffer,
274 ids: &[EntityId],
275 ) -> Result<(), RepositoryError> {
276 let entities = self.redb_table.get_multi(ids)?;
277 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
278 return Ok(());
279 }
280
281 let affected_owner_ids: Vec<EntityId> = {
287 let owner_repo = repository_factory::write::create_block_repository(self.transaction);
288 owner_repo
289 .get_relationships_from_right_ids(&BlockRelationshipField::Elements, ids)?
290 .into_iter()
291 .map(|(owner_id, _)| owner_id)
292 .collect()
293 };
294 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
296 std::collections::HashMap::new();
297 for owner_id in &affected_owner_ids {
298 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
299 }
300
301 self.redb_table.remove_multi(ids)?;
302 event_buffer.push(Event {
303 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(EntityEvent::Removed)),
304 ids: ids.into(),
305 data: None,
306 });
307 {
309 let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
310 for owner_id in &affected_owner_ids {
311 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
312 let updated: Vec<EntityId> = rel_ids
313 .iter()
314 .copied()
315 .filter(|rid| !removed_set.contains(rid))
316 .collect();
317 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
318 }
319 }
320 }
321
322 Ok(())
323 }
324 pub fn get_relationships_from_owner(
325 &self,
326 owner_id: &EntityId,
327 ) -> Result<Vec<EntityId>, RepositoryError> {
328 let repo = repository_factory::write::create_block_repository(self.transaction);
329 repo.get_relationship(owner_id, &BlockRelationshipField::Elements)
330 }
331
332 pub fn set_relationships_in_owner(
333 &mut self,
334 event_buffer: &mut EventBuffer,
335 owner_id: &EntityId,
336 ids: &[EntityId],
337 ) -> Result<(), RepositoryError> {
338 let mut repo = repository_factory::write::create_block_repository(self.transaction);
339 repo.set_relationship(
340 event_buffer,
341 owner_id,
342 &BlockRelationshipField::Elements,
343 ids,
344 )
345 }
346
347 pub fn snapshot(&self, _ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
348 let store_snap = self.transaction.snapshot_store();
349 Ok(EntityTreeSnapshot {
350 store_snapshot: Some(store_snap),
351 })
352 }
353
354 pub fn restore(
355 &mut self,
356 event_buffer: &mut EventBuffer,
357 snap: &EntityTreeSnapshot,
358 ) -> Result<(), RepositoryError> {
359 let store_snap = snap
360 .store_snapshot
361 .as_ref()
362 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
363 self.transaction.restore_store(store_snap);
364
365 let store = self.transaction.get_store();
366
367 let elem_ids: Vec<_> = store
369 .inline_elements
370 .read()
371 .unwrap()
372 .keys()
373 .copied()
374 .collect();
375 if !elem_ids.is_empty() {
376 event_buffer.push(Event {
377 origin: Origin::DirectAccess(DirectAccessEntity::InlineElement(
378 EntityEvent::Created,
379 )),
380 ids: elem_ids,
381 data: None,
382 });
383 }
384
385 Ok(())
386 }
387}
388
389pub struct InlineElementRepositoryRO<'a> {
390 redb_table: Box<dyn InlineElementTableRO + 'a>,
391}
392impl<'a> InlineElementRepositoryRO<'a> {
393 pub fn new(redb_table: Box<dyn InlineElementTableRO + 'a>) -> Self {
394 InlineElementRepositoryRO { redb_table }
395 }
396 pub fn get(&self, id: &EntityId) -> Result<Option<InlineElement>, RepositoryError> {
397 self.redb_table.get(id)
398 }
399 pub fn get_multi(
400 &self,
401 ids: &[EntityId],
402 ) -> Result<Vec<Option<InlineElement>>, RepositoryError> {
403 self.redb_table.get_multi(ids)
404 }
405 pub fn get_all(&self) -> Result<Vec<InlineElement>, RepositoryError> {
406 self.redb_table.get_all()
407 }
408}