text-document-common 1.4.0

Shared entities, database, events, and undo/redo infrastructure for text-document
Documentation
// Generated by Qleany v1.5.1 from common_da_use_cases_create_orphan.tera

use super::traits::WriteUoWFactory;
use crate::types::HasId;
use crate::undo_redo::UndoRedoCommand;
use anyhow::{Ok, Result};
use std::any::Any;
use std::collections::VecDeque;

// ---------------------------------------------------------------------------
// Non-undoable create-orphan
// ---------------------------------------------------------------------------

pub struct CreateOrphanUseCase<F: WriteUoWFactory> {
    uow_factory: F,
}

impl<F: WriteUoWFactory> CreateOrphanUseCase<F> {
    pub fn new(uow_factory: F) -> Self {
        CreateOrphanUseCase { uow_factory }
    }

    pub fn execute(&mut self, entity: &F::Entity) -> Result<F::Entity> {
        let results = self.execute_multi(std::slice::from_ref(entity))?;
        results
            .into_iter()
            .next()
            .ok_or_else(|| anyhow::anyhow!("Create orphan returned empty"))
    }

    pub fn execute_multi(&mut self, entities: &[F::Entity]) -> Result<Vec<F::Entity>> {
        let mut uow = self.uow_factory.create();
        uow.begin_transaction()?;
        let created = uow.create_orphan_multi(entities)?;
        uow.commit()?;
        Ok(created)
    }
}

// ---------------------------------------------------------------------------
// Undoable create-orphan
// ---------------------------------------------------------------------------

pub struct UndoableCreateOrphanUseCase<F: WriteUoWFactory> {
    uow_factory: F,
    undo_stack: VecDeque<Vec<F::Entity>>,
    redo_stack: VecDeque<Vec<F::Entity>>,
}

impl<F: WriteUoWFactory> UndoableCreateOrphanUseCase<F> {
    pub fn new(uow_factory: F) -> Self {
        UndoableCreateOrphanUseCase {
            uow_factory,
            undo_stack: VecDeque::new(),
            redo_stack: VecDeque::new(),
        }
    }

    pub fn execute(&mut self, entity: &F::Entity) -> Result<F::Entity> {
        let results = self.execute_multi(std::slice::from_ref(entity))?;
        results
            .into_iter()
            .next()
            .ok_or_else(|| anyhow::anyhow!("Create orphan returned empty"))
    }

    pub fn execute_multi(&mut self, entities: &[F::Entity]) -> Result<Vec<F::Entity>> {
        let mut uow = self.uow_factory.create();
        uow.begin_transaction()?;
        let created = uow.create_orphan_multi(entities)?;
        uow.commit()?;
        self.undo_stack.push_back(created.clone());
        self.redo_stack.clear();
        Ok(created)
    }
}

impl<F: WriteUoWFactory + Send + 'static> UndoRedoCommand for UndoableCreateOrphanUseCase<F>
where
    F::Entity: 'static,
{
    fn undo(&mut self) -> Result<()> {
        if let Some(last_entities) = self.undo_stack.pop_back() {
            let mut uow = self.uow_factory.create();
            uow.begin_transaction()?;
            uow.remove_multi(&last_entities.iter().map(|e| e.id()).collect::<Vec<_>>())?;
            uow.commit()?;
            self.redo_stack.push_back(last_entities);
        }
        Ok(())
    }

    fn redo(&mut self) -> Result<()> {
        if let Some(last_entities) = self.redo_stack.pop_back() {
            let mut uow = self.uow_factory.create();
            uow.begin_transaction()?;
            uow.create_orphan_multi(&last_entities)?;
            uow.commit()?;
            self.undo_stack.push_back(last_entities);
        }
        Ok(())
    }

    fn as_any(&self) -> &dyn Any {
        self
    }
}