text-document-direct-access 1.4.0

Entity CRUD controllers and DTOs for text-document
Documentation
// Generated by Qleany v1.5.0 from entity_units_of_work.tera

use anyhow::{Ok, Result};
use common::database::{CommandUnitOfWork, QueryUnitOfWork};
use common::database::{db_context::DbContext, transactions::Transaction};
use common::direct_access::block::BlockRelationshipField;
use common::direct_access::repository_factory;
use common::direct_access::use_cases;
use common::entities::Block;
use common::event::{AllEvent, DirectAccessEntity, Event, EventBuffer, EventHub, Origin};
use common::snapshot::EntityTreeSnapshot;
use common::types;
use common::types::EntityId;
use std::cell::RefCell;
use std::sync::Arc;

// ===========================================================================
// Write UoW
// ===========================================================================

pub struct BlockWriteUoW {
    context: DbContext,
    transaction: Option<Transaction>,
    event_hub: Arc<EventHub>,
    event_buffer: RefCell<EventBuffer>,
}

impl BlockWriteUoW {
    pub fn new(db_context: &DbContext, event_hub: &Arc<EventHub>) -> Self {
        BlockWriteUoW {
            context: db_context.clone(),
            transaction: None,
            event_hub: event_hub.clone(),
            event_buffer: RefCell::new(EventBuffer::new()),
        }
    }
}

impl CommandUnitOfWork for BlockWriteUoW {
    fn begin_transaction(&mut self) -> Result<()> {
        self.transaction = Some(Transaction::begin_write_transaction(&self.context)?);
        self.event_buffer.get_mut().begin_buffering();
        Ok(())
    }

    fn commit(&mut self) -> Result<()> {
        self.transaction.take().unwrap().commit()?;
        for event in self.event_buffer.get_mut().flush() {
            self.event_hub.send_event(event);
        }
        Ok(())
    }

    fn rollback(&mut self) -> Result<()> {
        self.transaction.take().unwrap().rollback()?;
        self.event_buffer.get_mut().discard();
        Ok(())
    }

    fn create_savepoint(&self) -> Result<types::Savepoint> {
        self.transaction.as_ref().unwrap().create_savepoint()
    }

    fn restore_to_savepoint(&mut self, savepoint: types::Savepoint) -> Result<()> {
        let mut transaction = self.transaction.take().unwrap();
        transaction.restore_to_savepoint(savepoint)?;

        // Discard buffered events — savepoint restore invalidated them
        self.event_buffer.get_mut().discard();

        // Send Reset immediately (not buffered — UI must refresh now)
        self.event_hub.send_event(Event {
            origin: Origin::DirectAccess(DirectAccessEntity::All(AllEvent::Reset)),
            ids: vec![],
            data: None,
        });

        // Recreate the transaction after restoring to savepoint
        self.transaction = Some(transaction);

        Ok(())
    }
}

impl use_cases::WriteUoW for BlockWriteUoW {
    type Entity = Block;

    fn get(&self, id: &EntityId) -> Result<Option<Block>> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let repo = repository_factory::write::create_block_repository(transaction);
        Ok(repo.get(id)?)
    }

    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Block>>> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let repo = repository_factory::write::create_block_repository(transaction);
        Ok(repo.get_multi(ids)?)
    }

    fn get_all(&self) -> Result<Vec<Block>> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let repo = repository_factory::write::create_block_repository(transaction);
        Ok(repo.get_all()?)
    }

    fn create_orphan_multi(&self, entities: &[Block]) -> Result<Vec<Block>> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        Ok(repo.create_orphan_multi(&mut event_buffer, entities)?)
    }

    fn update_multi(&self, entities: &[Block]) -> Result<Vec<Block>> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        Ok(repo.update_multi(&mut event_buffer, entities)?)
    }

    fn update_with_relationships_multi(&self, entities: &[Block]) -> Result<Vec<Block>> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        Ok(repo.update_with_relationships_multi(&mut event_buffer, entities)?)
    }

    fn remove(&self, id: &EntityId) -> Result<()> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        Ok(repo.remove(&mut event_buffer, id)?)
    }

    fn remove_multi(&self, ids: &[EntityId]) -> Result<()> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        Ok(repo.remove_multi(&mut event_buffer, ids)?)
    }

    fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let repo = repository_factory::write::create_block_repository(transaction);
        Ok(repo.snapshot(ids)?)
    }

    fn restore(&self, snap: &EntityTreeSnapshot) -> Result<()> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        Ok(repo.restore(&mut event_buffer, snap)?)
    }
}

impl use_cases::OwnedWriteUoW for BlockWriteUoW {
    fn create_multi(
        &self,
        entities: &[Block],
        owner_id: EntityId,
        index: i32,
    ) -> Result<Vec<Block>> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        Ok(repo.create_multi(&mut event_buffer, entities, owner_id, index)?)
    }

    fn get_relationships_from_owner(&self, owner_id: &EntityId) -> Result<Vec<EntityId>> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let repo = repository_factory::write::create_block_repository(transaction);
        Ok(repo.get_relationships_from_owner(owner_id)?)
    }

    fn set_relationships_in_owner(&self, owner_id: &EntityId, ids: &[EntityId]) -> Result<()> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        repo.set_relationships_in_owner(&mut event_buffer, owner_id, ids)?;
        Ok(())
    }
}

impl use_cases::WriteRelUoW<BlockRelationshipField> for BlockWriteUoW {
    fn set_relationship(
        &self,
        id: &EntityId,
        field: &BlockRelationshipField,
        right_ids: &[EntityId],
    ) -> Result<()> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        repo.set_relationship(&mut event_buffer, id, field, right_ids)?;
        Ok(())
    }

    fn move_relationship(
        &self,
        id: &EntityId,
        field: &BlockRelationshipField,
        ids_to_move: &[EntityId],
        new_index: i32,
    ) -> Result<Vec<EntityId>> {
        let transaction = self.transaction.as_ref().expect("Transaction not started");
        let mut repo = repository_factory::write::create_block_repository(transaction);
        let mut event_buffer = self.event_buffer.borrow_mut();
        Ok(repo.move_relationship_ids(&mut event_buffer, id, field, ids_to_move, new_index)?)
    }
}

// ---------------------------------------------------------------------------
// Write UoW Factory
// ---------------------------------------------------------------------------

pub struct BlockWriteUoWFactory {
    context: DbContext,
    event_hub: Arc<EventHub>,
}

impl BlockWriteUoWFactory {
    pub fn new(db_context: &DbContext, event_hub: &Arc<EventHub>) -> Self {
        BlockWriteUoWFactory {
            context: db_context.clone(),
            event_hub: event_hub.clone(),
        }
    }
}

impl use_cases::WriteUoWFactory for BlockWriteUoWFactory {
    type Entity = Block;
    fn create(&self) -> Box<dyn use_cases::WriteUoW<Entity = Block>> {
        Box::new(BlockWriteUoW::new(&self.context, &self.event_hub))
    }
}

impl use_cases::OwnedWriteUoWFactory for BlockWriteUoWFactory {
    type Entity = Block;
    fn create(&self) -> Box<dyn use_cases::OwnedWriteUoW<Entity = Block>> {
        Box::new(BlockWriteUoW::new(&self.context, &self.event_hub))
    }
}

impl use_cases::WriteRelUoWFactory<BlockRelationshipField> for BlockWriteUoWFactory {
    fn create(&self) -> Box<dyn use_cases::WriteRelUoW<BlockRelationshipField>> {
        Box::new(BlockWriteUoW::new(&self.context, &self.event_hub))
    }
}

// ===========================================================================
// Read-Only UoW
// ===========================================================================

pub struct BlockReadUoW {
    context: DbContext,
    transaction: RefCell<Option<Transaction>>,
}

impl BlockReadUoW {
    pub fn new(db_context: &DbContext) -> Self {
        BlockReadUoW {
            context: db_context.clone(),
            transaction: RefCell::new(None),
        }
    }
}

impl QueryUnitOfWork for BlockReadUoW {
    fn begin_transaction(&self) -> Result<()> {
        self.transaction
            .replace(Some(Transaction::begin_read_transaction(&self.context)?));
        Ok(())
    }

    fn end_transaction(&self) -> Result<()> {
        self.transaction.take().unwrap().end_read_transaction()?;
        Ok(())
    }
}

impl use_cases::ReadUoW for BlockReadUoW {
    type Entity = Block;

    fn get(&self, id: &EntityId) -> Result<Option<Block>> {
        let transaction = self.transaction.borrow();
        let repo = repository_factory::read::create_block_repository(transaction.as_ref().unwrap());
        Ok(repo.get(id)?)
    }

    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Block>>> {
        let transaction = self.transaction.borrow();
        let repo = repository_factory::read::create_block_repository(transaction.as_ref().unwrap());
        Ok(repo.get_multi(ids)?)
    }

    fn get_all(&self) -> Result<Vec<Block>> {
        let transaction = self.transaction.borrow();
        let repo = repository_factory::read::create_block_repository(transaction.as_ref().unwrap());
        Ok(repo.get_all()?)
    }
}

impl use_cases::ReadRelUoW<BlockRelationshipField> for BlockReadUoW {
    fn get_relationship(
        &self,
        id: &EntityId,
        field: &BlockRelationshipField,
    ) -> Result<Vec<EntityId>> {
        let transaction = self.transaction.borrow();
        let repo = repository_factory::read::create_block_repository(transaction.as_ref().unwrap());
        Ok(repo.get_relationship(id, field)?)
    }

    fn get_relationship_many(
        &self,
        ids: &[EntityId],
        field: &BlockRelationshipField,
    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>> {
        let transaction = self.transaction.borrow();
        let repo = repository_factory::read::create_block_repository(transaction.as_ref().unwrap());
        Ok(repo.get_relationship_many(ids, field)?)
    }

    fn get_relationship_count(
        &self,
        id: &EntityId,
        field: &BlockRelationshipField,
    ) -> Result<usize> {
        let transaction = self.transaction.borrow();
        let repo = repository_factory::read::create_block_repository(transaction.as_ref().unwrap());
        Ok(repo.get_relationship_count(id, field)?)
    }

    fn get_relationship_in_range(
        &self,
        id: &EntityId,
        field: &BlockRelationshipField,
        offset: usize,
        limit: usize,
    ) -> Result<Vec<EntityId>> {
        let transaction = self.transaction.borrow();
        let repo = repository_factory::read::create_block_repository(transaction.as_ref().unwrap());
        Ok(repo.get_relationship_in_range(id, field, offset, limit)?)
    }
}

// ---------------------------------------------------------------------------
// Read-Only UoW Factory
// ---------------------------------------------------------------------------

pub struct BlockReadUoWFactory {
    context: DbContext,
}

impl BlockReadUoWFactory {
    pub fn new(db_context: &DbContext) -> Self {
        BlockReadUoWFactory {
            context: db_context.clone(),
        }
    }
}

impl use_cases::ReadUoWFactory for BlockReadUoWFactory {
    type Entity = Block;
    fn create(&self) -> Box<dyn use_cases::ReadUoW<Entity = Block>> {
        Box::new(BlockReadUoW::new(&self.context))
    }
}

impl use_cases::ReadRelUoWFactory<BlockRelationshipField> for BlockReadUoWFactory {
    fn create(&self) -> Box<dyn use_cases::ReadRelUoW<BlockRelationshipField>> {
        Box::new(BlockReadUoW::new(&self.context))
    }
}