v-common-v8 0.1.30

common part of the veda platform
Documentation
use std::collections::{HashMap, HashSet};
use std::string::ToString;
use v_module::module::indv_apply_cmd;
use v_module::remote_indv_r_storage::get_individual;
use v_module::v_api::app::ResultCode;
use v_module::v_api::{APIClient, IndvOp, ALL_MODULES};
use v_module::v_onto::individual::Individual;
use v_module::v_onto::onto::Onto;
use v_module::v_onto::parser::parse_raw;

pub struct CallbackSharedData {
    pub g_key2indv: HashMap<String, Individual>,
    pub g_key2attr: HashMap<String, String>,
}

impl Default for CallbackSharedData {
    fn default() -> Self {
        Self {
            g_key2indv: Default::default(),
            g_key2attr: Default::default(),
        }
    }
}

impl CallbackSharedData {
    pub fn set_g_parent_script_id_etc(&mut self, event_id: &str) {
        let mut event_id = event_id;

        if !event_id.is_empty() {
            let mut aa: Vec<&str> = event_id.split(';').collect();
            if !aa.is_empty() {
                event_id = aa.get(0).unwrap();
            }

            aa = event_id.split('+').collect();

            if aa.len() >= 2 {
                self.g_key2attr.insert("$parent_script_id".to_owned(), aa.get(1).unwrap().to_string());
                self.g_key2attr.insert("$parent_document_id".to_owned(), aa.get(0).unwrap().to_string());
            } else {
                self.g_key2attr.insert("$parent_script_id".to_owned(), String::default());
                self.g_key2attr.insert("$parent_document_id".to_owned(), String::default());
            }
        } else {
            self.g_key2attr.insert("$parent_script_id".to_owned(), String::default());
            self.g_key2attr.insert("$parent_document_id".to_owned(), String::default());
        }
    }

    pub fn set_g_super_classes(&mut self, indv_types: &[String], onto: &Onto) {
        let mut super_classes = HashSet::new();

        for indv_type in indv_types.iter() {
            onto.get_supers(indv_type, &mut super_classes);
        }

        let mut g_super_classes = String::new();

        g_super_classes.push('[');
        for s in super_classes.iter() {
            if g_super_classes.len() > 2 {
                g_super_classes.push(',');
            }
            g_super_classes.push('"');
            g_super_classes.push_str(s);
            g_super_classes.push('"');
        }
        g_super_classes.push(']');

        self.g_key2attr.insert("$super_classes".to_owned(), g_super_classes);
    }
}

pub struct TransactionItem {
    uri: String,
    pub cmd: IndvOp,
    pub indv: Individual,
    ticket_id: String,
    pub rc: ResultCode,
}

pub struct Transaction {
    pub sys_ticket: String,
    pub id: i64,
    pub event_id: String,
    buff: HashMap<String, usize>,
    pub queue: Vec<TransactionItem>,
    pub src: String,
}

impl Default for Transaction {
    fn default() -> Self {
        Self {
            sys_ticket: "".to_string(),
            id: 0,
            event_id: "".to_string(),
            buff: Default::default(),
            queue: vec![],
            src: "".to_string(),
        }
    }
}

impl Transaction {
    fn add_item(&mut self, item: TransactionItem) {
        self.buff.insert(item.uri.clone(), self.queue.len());
        self.queue.push(item);
    }

    pub(crate) fn get_indv(&mut self, id: &str) -> Option<&mut Individual> {
        if let Some(idx) = self.buff.get(id) {
            if let Some(ti) = self.queue.get_mut(*idx) {
                return Some(&mut ti.indv);
            }
        }

        None
    }

    pub(crate) fn add_to_transaction(&mut self, cmd: IndvOp, new_indv: Individual, ticket_id: String, _user_id: String) -> ResultCode {
        let mut ti = TransactionItem {
            uri: "".to_string(),
            cmd,
            indv: new_indv,
            ticket_id,
            rc: ResultCode::Ok,
        };

        if ti.cmd == IndvOp::Remove {
        } else {
            ti.uri = ti.indv.get_id().to_string();

            if ti.cmd == IndvOp::AddTo || ti.cmd == IndvOp::SetIn || ti.cmd == IndvOp::RemoveFrom {
                if let Some(mut prev_indv) = self.get_indv(ti.indv.get_id()) {
                    debug!("{:?} BEFORE: {}", ti.cmd, &prev_indv);
                    debug!("{:?} APPLY: {}", ti.cmd, &ti.indv);
                    indv_apply_cmd(&ti.cmd, &mut prev_indv, &mut ti.indv);
                    debug!("{:?} AFTER: {}", ti.cmd, &prev_indv);
                    ti.indv = Individual::new_from_obj(prev_indv.get_obj());
                } else if let Some(mut prev_indv) = get_individual(ti.indv.get_id()) {
                    if parse_raw(&mut prev_indv).is_ok() {
                        prev_indv.parse_all();
                        debug!("{:?} BEFORE: {}", ti.cmd, &prev_indv);
                        debug!("{:?} APPLY: {}", ti.cmd, &ti.indv);
                        indv_apply_cmd(&ti.cmd, &mut prev_indv, &mut ti.indv);
                        debug!("{:?} AFTER: {}", ti.cmd, &prev_indv);
                        ti.indv = prev_indv;
                    } else {
                        ti.rc = ResultCode::UnprocessableEntity;
                    }
                } else {
                    ti.rc = ResultCode::UnprocessableEntity;
                }

                ti.cmd = IndvOp::Put;
            }
        }

        if ti.rc == ResultCode::Ok {
            self.add_item(ti);
            ResultCode::Ok
        } else {
            ti.rc
        }
    }
}

pub fn commit(tnx: &Transaction, api_client: &mut APIClient) -> ResultCode {
    for ti in tnx.queue.iter() {
        if ti.cmd == IndvOp::Remove && ti.indv.get_id().is_empty() {
            continue;
        }

        if ti.rc != ResultCode::Ok {
            return ti.rc;
        }

        if ti.indv.get_id().is_empty() || ti.indv.get_id().len() < 2 {
            warn!("skip individual with invalid id: {}", ti.indv.to_string());
            continue;
        }

        debug!("commit {}", &ti.indv);
        let res = api_client.update_use_param(&ti.ticket_id, &tnx.event_id, &tnx.src, ALL_MODULES, ti.cmd.clone(), &ti.indv);
        if res.result != ResultCode::Ok {
            error!("commit: op_id={}, code={:?}", res.op_id, res.result);
            if res.result != ResultCode::NotReady {
                return res.result;
            }
        }
    }

    ResultCode::Ok
}