use crate::database::Store;
use crate::entities::Resource;
use crate::error::RepositoryError;
use crate::types::EntityId;
use super::resource_repository::ResourceTable;
use super::resource_repository::ResourceTableRO;
pub struct ResourceHashMapTable<'a> {
store: &'a Store,
}
impl<'a> ResourceHashMapTable<'a> {
pub fn new(store: &'a Store) -> Self {
Self { store }
}
}
impl<'a> ResourceTable for ResourceHashMapTable<'a> {
fn create(&mut self, entity: &Resource) -> Result<Resource, RepositoryError> {
self.create_multi(std::slice::from_ref(entity))
.map(|v| v.into_iter().next().unwrap())
}
fn create_multi(&mut self, entities: &[Resource]) -> Result<Vec<Resource>, RepositoryError> {
let mut created = Vec::with_capacity(entities.len());
let mut map = self.store.resources.write().unwrap();
for entity in entities {
let new_entity = if entity.id == EntityId::default() {
let id = self.store.next_id("resource");
Resource {
id,
..entity.clone()
}
} else {
if map.contains_key(&entity.id) {
return Err(RepositoryError::DuplicateId {
entity: "Resource",
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<Resource>, RepositoryError> {
Ok(self.store.resources.read().unwrap().get(id).cloned())
}
fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError> {
let map = self.store.resources.read().unwrap();
Ok(ids.iter().map(|id| map.get(id).cloned()).collect())
}
fn get_all(&self) -> Result<Vec<Resource>, RepositoryError> {
Ok(self
.store
.resources
.read()
.unwrap()
.values()
.cloned()
.collect())
}
fn update(&mut self, entity: &Resource) -> Result<Resource, RepositoryError> {
self.update_multi(std::slice::from_ref(entity))
.map(|v| v.into_iter().next().unwrap())
}
fn update_multi(&mut self, entities: &[Resource]) -> Result<Vec<Resource>, RepositoryError> {
let mut map = self.store.resources.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: &Resource,
) -> Result<Resource, RepositoryError> {
self.update(entity)
}
fn update_with_relationships_multi(
&mut self,
entities: &[Resource],
) -> Result<Vec<Resource>, 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.resources.write().unwrap();
for id in ids {
map.remove(id);
}
}
{
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.resources.iter().any(|rid| removed.contains(rid)) {
let mut updated = d.clone();
updated.resources.retain(|rid| !removed.contains(rid));
Some((*did, updated))
} else {
None
}
})
.collect();
for (did, d) in updates {
doc_map.insert(did, d);
}
}
Ok(())
}
}
pub struct ResourceHashMapTableRO<'a> {
store: &'a Store,
}
impl<'a> ResourceHashMapTableRO<'a> {
pub fn new(store: &'a Store) -> Self {
Self { store }
}
}
impl<'a> ResourceTableRO for ResourceHashMapTableRO<'a> {
fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError> {
Ok(self.store.resources.read().unwrap().get(id).cloned())
}
fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError> {
let map = self.store.resources.read().unwrap();
Ok(ids.iter().map(|id| map.get(id).cloned()).collect())
}
fn get_all(&self) -> Result<Vec<Resource>, RepositoryError> {
Ok(self
.store
.resources
.read()
.unwrap()
.values()
.cloned()
.collect())
}
}