use crate::database::Store;
use crate::entities::List;
use crate::error::RepositoryError;
use crate::types::EntityId;
use super::list_repository::ListTable;
use super::list_repository::ListTableRO;
pub struct ListHashMapTable<'a> {
store: &'a Store,
}
impl<'a> ListHashMapTable<'a> {
pub fn new(store: &'a Store) -> Self {
Self { store }
}
}
impl<'a> ListTable for ListHashMapTable<'a> {
fn create(&mut self, entity: &List) -> Result<List, RepositoryError> {
self.create_multi(std::slice::from_ref(entity))
.map(|v| v.into_iter().next().unwrap())
}
fn create_multi(&mut self, entities: &[List]) -> Result<Vec<List>, RepositoryError> {
let mut created = Vec::with_capacity(entities.len());
let mut map = self.store.lists.write().unwrap();
for entity in entities {
let new_entity = if entity.id == EntityId::default() {
let id = self.store.next_id("list");
List {
id,
..entity.clone()
}
} else {
if map.contains_key(&entity.id) {
return Err(RepositoryError::DuplicateId {
entity: "List",
id: entity.id,
});
}
entity.clone()
};
map.insert(new_entity.id, new_entity.clone());
created.push(new_entity);
}
Ok(created)
}
fn get(&self, id: &EntityId) -> Result<Option<List>, RepositoryError> {
Ok(self.store.lists.read().unwrap().get(id).cloned())
}
fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<List>>, RepositoryError> {
let map = self.store.lists.read().unwrap();
Ok(ids.iter().map(|id| map.get(id).cloned()).collect())
}
fn get_all(&self) -> Result<Vec<List>, RepositoryError> {
Ok(self.store.lists.read().unwrap().values().cloned().collect())
}
fn update(&mut self, entity: &List) -> Result<List, RepositoryError> {
self.update_multi(std::slice::from_ref(entity))
.map(|v| v.into_iter().next().unwrap())
}
fn update_multi(&mut self, entities: &[List]) -> Result<Vec<List>, RepositoryError> {
let mut map = self.store.lists.write().unwrap();
let mut result = Vec::with_capacity(entities.len());
for entity in entities {
map.insert(entity.id, entity.clone());
result.push(entity.clone());
}
Ok(result)
}
fn update_with_relationships(&mut self, entity: &List) -> Result<List, RepositoryError> {
self.update(entity)
}
fn update_with_relationships_multi(
&mut self,
entities: &[List],
) -> Result<Vec<List>, RepositoryError> {
self.update_multi(entities)
}
fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError> {
self.remove_multi(std::slice::from_ref(id))
}
fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError> {
let removed: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
{
let mut map = self.store.lists.write().unwrap();
for id in ids {
map.remove(id);
}
}
{
let mut block_map = self.store.blocks.write().unwrap();
let updates: Vec<(EntityId, crate::entities::Block)> = block_map
.iter()
.filter_map(|(bid, b)| {
b.list.filter(|l| removed.contains(l)).map(|_| {
let mut updated = b.clone();
updated.list = None;
(*bid, updated)
})
})
.collect();
for (bid, b) in updates {
block_map.insert(bid, b);
}
}
{
let mut doc_map = self.store.documents.write().unwrap();
let updates: Vec<(EntityId, crate::entities::Document)> = doc_map
.iter()
.filter_map(|(did, d)| {
if d.lists.iter().any(|lid| removed.contains(lid)) {
let mut updated = d.clone();
updated.lists.retain(|lid| !removed.contains(lid));
Some((*did, updated))
} else {
None
}
})
.collect();
for (did, d) in updates {
doc_map.insert(did, d);
}
}
Ok(())
}
}
pub struct ListHashMapTableRO<'a> {
store: &'a Store,
}
impl<'a> ListHashMapTableRO<'a> {
pub fn new(store: &'a Store) -> Self {
Self { store }
}
}
impl<'a> ListTableRO for ListHashMapTableRO<'a> {
fn get(&self, id: &EntityId) -> Result<Option<List>, RepositoryError> {
Ok(self.store.lists.read().unwrap().get(id).cloned())
}
fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<List>>, RepositoryError> {
let map = self.store.lists.read().unwrap();
Ok(ids.iter().map(|id| map.get(id).cloned()).collect())
}
fn get_all(&self) -> Result<Vec<List>, RepositoryError> {
Ok(self.store.lists.read().unwrap().values().cloned().collect())
}
}