logisheets_controller 0.7.0

the core of LogiSheets
Documentation
use std::collections::HashSet;

use logisheets_base::block_affect::BlockAffectTrait;
use logisheets_base::errors::BasicError;
use logisheets_base::get_book_name::GetBookNameTrait;
use logisheets_base::id_fetcher::{IdFetcherTrait, SheetIdFetcherByIdxTrait, VertexFetcherTrait};
use logisheets_base::matrix_value::cross_product_usize;
use logisheets_base::{
    BlockCellId, BlockId, CellId, ColId, Cube, CubeId, ExtBookId, ExtRef, ExtRefId, FuncId, NameId,
    NormalCellId, Range, RangeId, RowId, SheetId, TextId,
};

use crate::container::DataContainer;
use crate::cube_manager::CubeManager;
use crate::ext_book_manager::ExtBooksManager;
use crate::ext_ref_manager::ExtRefManager;
use crate::formula_manager::ctx::FormulaExecCtx;
use crate::id_manager::{FuncIdManager, NameIdManager, SheetIdManager, TextIdManager};
use crate::navigator::Navigator;
use crate::range_manager::RangeManager;
use crate::workbook::sheet_pos_manager::SheetPosManager;

use super::IdFetcher;

type Result<T> = std::result::Result<T, BasicError>;

pub struct FormulaConnector<'a> {
    pub book_name: &'a str,
    pub container: &'a mut DataContainer,
    pub sheet_pos_manager: &'a mut SheetPosManager,
    pub sheet_id_manager: &'a mut SheetIdManager,
    pub text_id_manager: &'a mut TextIdManager,
    pub func_id_manager: &'a mut FuncIdManager,
    pub range_manager: &'a mut RangeManager,
    pub cube_manager: &'a mut CubeManager,
    pub ext_ref_manager: &'a mut ExtRefManager,
    pub name_id_manager: &'a mut NameIdManager,
    pub id_navigator: &'a Navigator,
    pub idx_navigator: &'a Navigator,
    pub external_links_manager: &'a mut ExtBooksManager,

    pub dirty_ranges: HashSet<(SheetId, RangeId)>,
    pub dirty_cubes: HashSet<CubeId>,
}

impl<'a> FormulaConnector<'a> {
    fn get_id_fetcher(&mut self) -> IdFetcher {
        IdFetcher {
            sheet_id_manager: self.sheet_id_manager,
            text_id_manager: self.text_id_manager,
            func_id_manager: self.func_id_manager,
            name_id_manager: self.name_id_manager,
            external_links_manager: self.external_links_manager,
            navigator: self.id_navigator,
        }
    }
}

impl<'a> IdFetcherTrait for FormulaConnector<'a> {
    fn fetch_row_id(&self, sheet_id: &SheetId, row_idx: usize) -> Result<RowId> {
        self.id_navigator.fetch_row_id(sheet_id, row_idx)
    }

    fn fetch_col_id(&self, sheet_id: &SheetId, col_idx: usize) -> Result<ColId> {
        self.id_navigator.fetch_col_id(sheet_id, col_idx)
    }

    fn fetch_cell_id(&self, sheet_id: &SheetId, row_idx: usize, col_idx: usize) -> Result<CellId> {
        self.id_navigator.fetch_cell_id(sheet_id, row_idx, col_idx)
    }

    fn fetch_sheet_id(&mut self, sheet_name: &str) -> SheetId {
        self.get_id_fetcher().fetch_sheet_id(sheet_name)
    }

    fn fetch_name_id(&mut self, workbook: &Option<&str>, name: &str) -> NameId {
        self.get_id_fetcher().fetch_name_id(workbook, name)
    }

    fn fetch_ext_book_id(&mut self, book: &str) -> ExtBookId {
        self.get_id_fetcher().fetch_ext_book_id(book)
    }

    fn fetch_text_id(&mut self, text: &str) -> TextId {
        self.get_id_fetcher().fetch_text_id(text)
    }

    fn fetch_func_id(&mut self, func_name: &str) -> FuncId {
        self.get_id_fetcher().fetch_func_id(func_name)
    }

    fn fetch_norm_cell_id(
        &self,
        sheet_id: &SheetId,
        row_idx: usize,
        col_idx: usize,
    ) -> Result<NormalCellId> {
        self.id_navigator
            .fetch_norm_cell_id(sheet_id, row_idx, col_idx)
    }

    fn fetch_block_cell_id(
        &self,
        sheet_id: &SheetId,
        block_id: &BlockId,
        row: usize,
        col: usize,
    ) -> Result<BlockCellId> {
        self.id_navigator
            .fetch_block_cell_id(sheet_id, block_id, row, col)
    }
}

impl<'a> GetBookNameTrait for FormulaConnector<'a> {
    fn get_book_name(&self) -> &str {
        self.book_name
    }
}
impl<'a> BlockAffectTrait for FormulaConnector<'a> {
    fn get_all_block_cells(
        &self,
        sheet_id: SheetId,
        block_id: BlockId,
    ) -> Result<Vec<BlockCellId>> {
        let bp = self.id_navigator.get_block_place(&sheet_id, &block_id)?;
        let mut res = Vec::<BlockCellId>::new();
        bp.rows.iter().for_each(|r| {
            bp.cols.iter().for_each(|c| {
                let bid = BlockCellId {
                    block_id,
                    row: r.clone(),
                    col: c.clone(),
                };
                res.push(bid)
            })
        });
        Ok(res)
    }

    fn get_master_cell(&self, sheet_id: SheetId, block_id: BlockId) -> Result<NormalCellId> {
        self.id_navigator.get_master_cell(&sheet_id, &block_id)
    }

    fn get_block_cells_by_line(
        &self,
        sheet_id: SheetId,
        block_id: BlockId,
        idx: usize,
        cnt: usize,
        is_row: bool,
    ) -> Result<Vec<BlockCellId>> {
        let bp = self.id_navigator.get_block_place(&sheet_id, &block_id)?;
        let (row_cnt, col_cnt) = bp.get_block_size();
        let (sr, sc, er, ec) = if is_row {
            let start_row = idx;
            let end_row = start_row + cnt - 1;
            (start_row, 0, end_row, col_cnt - 1)
        } else {
            let start_col = idx;
            let end_col = start_col + cnt - 1;
            (0, start_col, row_cnt - 1, end_col)
        };
        let cells = cross_product_usize(sr, er, sc, ec).into_iter().fold(
            Vec::new(),
            |prev, (r, c)| match bp.get_inner_id(r, c) {
                Some((rid, cid)) => {
                    let bid = BlockCellId {
                        block_id,
                        row: rid,
                        col: cid,
                    };
                    let mut res = prev;
                    res.push(bid);
                    res
                }
                None => prev,
            },
        );
        Ok(cells)
    }

    fn get_block_size(&self, sheet_id: SheetId, block_id: BlockId) -> Result<(usize, usize)> {
        self.id_navigator.get_block_size(&sheet_id, &block_id)
    }

    fn get_blocks_across_line(
        &self,
        sheet_id: SheetId,
        from_idx: usize,
        cnt: usize,
        is_row: bool,
    ) -> Result<Vec<BlockId>> {
        self.id_navigator
            .get_affected_blockplace(&sheet_id, from_idx, cnt, is_row)
    }

    fn any_other_blocks_in(
        &self,
        sheet_id: SheetId,
        block_id: BlockId,
        start_row: usize,
        end_row: usize,
        start_col: usize,
        end_col: usize,
    ) -> bool {
        self.idx_navigator
            .any_other_blocks_in(sheet_id, block_id, start_row, end_row, start_col, end_col)
    }

    fn get_affected_blockplace(
        &self,
        sheet_id: SheetId,
        line_idx: usize,
        cnt: usize,
        is_row: bool,
    ) -> std::prelude::v1::Result<Vec<BlockId>, BasicError> {
        self.id_navigator
            .get_affected_blockplace(&sheet_id, line_idx, cnt, is_row)
    }

    fn get_block_cell_id(
        &self,
        sheet_id: SheetId,
        block_id: BlockId,
        row: usize,
        col: usize,
    ) -> std::prelude::v1::Result<BlockCellId, BasicError> {
        self.id_navigator
            .fetch_block_cell_id(&sheet_id, &block_id, row, col)
    }
}

impl<'a> VertexFetcherTrait for FormulaConnector<'a> {
    fn fetch_range_id(&mut self, sheet_id: &SheetId, range: &Range) -> RangeId {
        self.range_manager.get_range_id(sheet_id, range)
    }

    fn fetch_cube_id(&mut self, cube: &Cube) -> CubeId {
        self.cube_manager.get_cube_id(cube)
    }

    fn fetch_ext_ref_id(&mut self, ext_ref: &ExtRef) -> ExtRefId {
        self.ext_ref_manager.get_ext_ref_id(ext_ref)
    }
}

impl<'a> SheetIdFetcherByIdxTrait for FormulaConnector<'a> {
    fn fetch_sheet_id_by_index(&self, idx: usize) -> std::prelude::v1::Result<SheetId, usize> {
        self.sheet_pos_manager
            .get_sheet_id(idx)
            .ok_or(self.sheet_pos_manager.pos.len())
    }
}

impl<'a> logisheets_parser::context::ContextTrait for FormulaConnector<'a> {}

impl<'a> FormulaExecCtx for FormulaConnector<'a> {
    fn remove_range_id(&mut self, sheet_id: &SheetId, range_id: &RangeId) {
        self.range_manager.remove_range_id(sheet_id, range_id)
    }

    fn remove_cube_id(&mut self, cube_id: &CubeId) {
        self.cube_manager.remove_cube(cube_id)
    }

    fn remove_ext_ref_id(&mut self, id: &ExtRefId) {
        self.ext_ref_manager.remove_ext_ref_id(id)
    }

    fn get_dirty_range_ids(&self) -> HashSet<(SheetId, RangeId)> {
        self.dirty_ranges.clone()
    }

    fn get_dirty_cube_ids(&self) -> HashSet<CubeId> {
        self.dirty_cubes.clone()
    }
}