use super::traits::WriteUoWFactory;
use crate::snapshot::EntityTreeSnapshot;
use crate::types::EntityId;
use crate::undo_redo::UndoRedoCommand;
use anyhow::{Ok, Result};
use std::any::Any;
pub struct RemoveUseCase<F: WriteUoWFactory> {
uow_factory: F,
}
impl<F: WriteUoWFactory> RemoveUseCase<F> {
pub fn new(uow_factory: F) -> Self {
RemoveUseCase { uow_factory }
}
pub fn execute(&mut self, id: &EntityId) -> Result<()> {
self.execute_multi(&[*id])
}
pub fn execute_multi(&mut self, ids: &[EntityId]) -> Result<()> {
let mut uow = self.uow_factory.create();
uow.begin_transaction()?;
for id in ids {
if uow.get(id)?.is_none() {
return Err(anyhow::anyhow!("Entity with id {} does not exist", id));
}
}
uow.remove_multi(ids)?;
uow.commit()?;
Ok(())
}
}
pub struct UndoableRemoveUseCase<F: WriteUoWFactory> {
uow_factory: F,
entity_tree_snapshot: Option<EntityTreeSnapshot>,
original_ids: Option<Vec<EntityId>>,
}
impl<F: WriteUoWFactory> UndoableRemoveUseCase<F> {
pub fn new(uow_factory: F) -> Self {
UndoableRemoveUseCase {
uow_factory,
entity_tree_snapshot: None,
original_ids: None,
}
}
pub fn execute(&mut self, id: &EntityId) -> Result<()> {
self.execute_multi(&[*id])
}
pub fn execute_multi(&mut self, ids: &[EntityId]) -> Result<()> {
let mut uow = self.uow_factory.create();
uow.begin_transaction()?;
for id in ids {
if uow.get(id)?.is_none() {
return Err(anyhow::anyhow!("Entity with id {} does not exist", id));
}
}
self.entity_tree_snapshot = Some(uow.snapshot(ids)?);
uow.remove_multi(ids)?;
uow.commit()?;
self.original_ids = Some(ids.to_vec());
Ok(())
}
}
impl<F: WriteUoWFactory + Send + 'static> UndoRedoCommand for UndoableRemoveUseCase<F>
where
F::Entity: 'static,
{
fn undo(&mut self) -> Result<()> {
if let Some(ref snap) = self.entity_tree_snapshot {
let mut uow = self.uow_factory.create();
uow.begin_transaction()?;
uow.restore(snap)?;
uow.commit()?;
}
Ok(())
}
fn redo(&mut self) -> Result<()> {
if let Some(ref ids) = self.original_ids {
let mut uow = self.uow_factory.create();
uow.begin_transaction()?;
self.entity_tree_snapshot = Some(uow.snapshot(ids)?);
uow.remove_multi(ids)?;
uow.commit()?;
}
Ok(())
}
fn as_any(&self) -> &dyn Any {
self
}
}