text-document-common 1.4.1

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

use super::traits::WriteRelUoWFactory;
use crate::types::{EntityId, Savepoint};
use crate::undo_redo::UndoRedoCommand;
use anyhow::Result;
use std::any::Any;
use std::collections::VecDeque;

// ---------------------------------------------------------------------------
// Non-undoable move-relationship
// ---------------------------------------------------------------------------

pub struct MoveRelationshipUseCase<RF, F: WriteRelUoWFactory<RF>> {
    uow_factory: F,
    _phantom: std::marker::PhantomData<RF>,
}

impl<RF, F: WriteRelUoWFactory<RF>> MoveRelationshipUseCase<RF, F> {
    pub fn new(uow_factory: F) -> Self {
        MoveRelationshipUseCase {
            uow_factory,
            _phantom: std::marker::PhantomData,
        }
    }

    pub fn execute(
        &mut self,
        id: &EntityId,
        field: &RF,
        ids_to_move: &[EntityId],
        new_index: i32,
    ) -> Result<Vec<EntityId>> {
        let mut uow = self.uow_factory.create();
        uow.begin_transaction()?;
        let result = uow.move_relationship(id, field, ids_to_move, new_index)?;
        uow.commit()?;
        Ok(result)
    }
}

// ---------------------------------------------------------------------------
// Undoable move-relationship
// ---------------------------------------------------------------------------

pub struct UndoableMoveRelationshipUseCase<RF: Clone, F: WriteRelUoWFactory<RF>> {
    uow_factory: F,
    undo_stack: VecDeque<Savepoint>,
    redo_stack: VecDeque<(EntityId, RF, Vec<EntityId>, i32)>,
}

impl<RF: Clone, F: WriteRelUoWFactory<RF>> UndoableMoveRelationshipUseCase<RF, F> {
    pub fn new(uow_factory: F) -> Self {
        UndoableMoveRelationshipUseCase {
            uow_factory,
            undo_stack: VecDeque::new(),
            redo_stack: VecDeque::new(),
        }
    }

    pub fn execute(
        &mut self,
        id: &EntityId,
        field: &RF,
        ids_to_move: &[EntityId],
        new_index: i32,
    ) -> Result<Vec<EntityId>> {
        let mut uow = self.uow_factory.create();
        uow.begin_transaction()?;
        let savepoint = uow.create_savepoint()?;
        let result = uow.move_relationship(id, field, ids_to_move, new_index)?;
        uow.commit()?;
        self.undo_stack.push_back(savepoint);
        self.redo_stack
            .push_back((*id, field.clone(), ids_to_move.to_vec(), new_index));
        Ok(result)
    }
}

impl<RF: Clone + Send + 'static, F: WriteRelUoWFactory<RF> + Send + 'static> UndoRedoCommand
    for UndoableMoveRelationshipUseCase<RF, F>
{
    fn undo(&mut self) -> Result<()> {
        if let Some(savepoint) = self.undo_stack.pop_back() {
            let mut uow = self.uow_factory.create();
            uow.begin_transaction()?;
            uow.restore_to_savepoint(savepoint)?;
            uow.commit()?;
        }
        Ok(())
    }

    fn redo(&mut self) -> Result<()> {
        if let Some((id, field, ids_to_move, new_index)) = self.redo_stack.pop_back() {
            let mut uow = self.uow_factory.create();
            uow.begin_transaction()?;
            let savepoint = uow.create_savepoint()?;
            uow.move_relationship(&id, &field, &ids_to_move, new_index)?;
            uow.commit()?;
            self.undo_stack.push_back(savepoint);
        }
        Ok(())
    }

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