use crate::ExportPlainTextDto;
use anyhow::{Result, anyhow};
use common::database::QueryUnitOfWork;
use common::database::rope_helpers::{block_content_via_store, rope_flat_text_if_simple};
use common::entities::{Block, Document, Frame, Root};
use common::types::{EntityId, ROOT_ENTITY_ID};
pub trait ExportPlainTextUnitOfWorkFactoryTrait: Send + Sync {
fn create(&self) -> Box<dyn ExportPlainTextUnitOfWorkTrait>;
}
#[macros::uow_action(entity = "Root", action = "GetRO")]
#[macros::uow_action(entity = "Root", action = "GetRelationshipRO")]
#[macros::uow_action(entity = "Document", action = "GetRO")]
#[macros::uow_action(entity = "Document", action = "GetRelationshipRO")]
#[macros::uow_action(entity = "Frame", action = "GetRO")]
#[macros::uow_action(entity = "Frame", action = "GetRelationshipRO")]
#[macros::uow_action(entity = "Block", action = "GetMultiRO")]
pub trait ExportPlainTextUnitOfWorkTrait: QueryUnitOfWork {}
pub struct ExportPlainTextUseCase {
uow_factory: Box<dyn ExportPlainTextUnitOfWorkFactoryTrait>,
}
impl ExportPlainTextUseCase {
pub fn new(uow_factory: Box<dyn ExportPlainTextUnitOfWorkFactoryTrait>) -> Self {
ExportPlainTextUseCase { uow_factory }
}
pub fn execute(&mut self) -> Result<ExportPlainTextDto> {
let uow = self.uow_factory.create();
uow.begin_transaction()?;
let root = uow
.get_root(&ROOT_ENTITY_ID)?
.ok_or_else(|| anyhow!("Root entity not found"))?;
let doc_ids = uow.get_root_relationship(
&root.id,
&common::direct_access::root::RootRelationshipField::Document,
)?;
let doc_id = *doc_ids
.first()
.ok_or_else(|| anyhow!("Root has no associated Document"))?;
let frame_ids = uow.get_document_relationship(
&doc_id,
&common::direct_access::document::DocumentRelationshipField::Frames,
)?;
let store = uow.store();
if let Some(plain_text) = rope_flat_text_if_simple(&store, frame_ids.len()) {
uow.end_transaction()?;
return Ok(ExportPlainTextDto { plain_text });
}
let mut all_plain_texts: Vec<String> = Vec::new();
for frame_id in &frame_ids {
let block_ids = uow.get_frame_relationship(
frame_id,
&common::direct_access::frame::FrameRelationshipField::Blocks,
)?;
if block_ids.is_empty() {
continue;
}
let blocks_opt = uow.get_block_multi(&block_ids)?;
let mut blocks: Vec<Block> = blocks_opt.into_iter().flatten().collect();
blocks.sort_by_key(|b| b.document_position);
for block in &blocks {
all_plain_texts.push(block_content_via_store(block, &store));
}
}
let plain_text = all_plain_texts.join("\n");
uow.end_transaction()?;
Ok(ExportPlainTextDto { plain_text })
}
}