v-common-onto 0.1.13

common part of the veda platform
Documentation
use crate::datatype::{DataType, Lang};
use crate::individual::Individual;
use serde_json::value::Value as JSONValue;
use serde_json::Map;

pub fn parse_json_to_individual(src: &JSONValue, dest: &mut Individual) -> bool {
    let mut res = true;

    if let Some(props) = src.as_object() {
        for (key, value) in props.iter() {
            if key == "@" {
                if let Some(id) = value.as_str() {
                    dest.set_id(id);
                } else {
                    error!("json->individual: fail get id");
                    res = false;
                }
            } else if let Some(values) = value.as_array() {
                if !json_to_predicate(key, values, dest) {
                    res = false;
                }
            } else {
                error!("json->individual: predicate [{}] must contain an array of values", key);
                res = false;
            }
        }
    }

    res
}

fn get_datatype_from_json(val: Option<&JSONValue>) -> Result<DataType, String> {
    if val.is_none() {
        return Err("not content field type".to_owned());
    }

    let tp = val.unwrap();
    if tp.is_string() {
        if let Some(v) = tp.as_str() {
            if let Some(d) = DataType::new_from_str(v) {
                return Ok(d);
            }
        }
    } else if tp.is_u64() {
        if let Some(v) = tp.as_u64() {
            if let Some(d) = DataType::new_from_u64(v) {
                return Ok(d);
            }
        }
    } else {
        return Err("expected string or integer for value of field [type]".to_owned());
    }

    Err("invalid value of field [type]".to_owned())
}

fn add_string(v: &Map<String, JSONValue>, vdata: &JSONValue, predicate: &str, dest: &mut Individual) {
    if let Some(s) = vdata.as_str() {
        let lang = if let Some(v) = v.get("lang") {
            if v.is_string() {
                Lang::new_from_str(v.as_str().unwrap_or_default().to_lowercase().as_str())
            } else if v.is_number() {
                Lang::new_from_i64(v.as_i64().unwrap_or_default())
            } else {
                Lang::NONE
            }
        } else {
            Lang::NONE
        };

        dest.add_string(predicate, s, lang);
    }
}

fn json_to_predicate(predicate: &str, values: &[JSONValue], dest: &mut Individual) -> bool {
    let mut res = true;
    for val in values {
        if let Some(v) = val.as_object() {
            let vdata = v.get("data");
            if vdata.is_none() {
                error!("json->individual: predicate [{}], value must contain [data]", predicate);
                res = false;
                continue;
            }
            let ptype = get_datatype_from_json(v.get("type"));
            if ptype.is_err() {
                error!("json->individual: predicate [{}], invalid value", predicate);
                res = false;
                continue;
            }
            let vdata = vdata.unwrap();

            match ptype.unwrap() {
                DataType::Uri => {
                    if let Some(v) = vdata.as_str() {
                        dest.add_uri(predicate, v);
                    }
                }
                DataType::String => add_string(v, vdata, predicate, dest),

                DataType::Integer => {
                    if let Some(v) = vdata.as_i64() {
                        dest.add_integer(predicate, v);
                    }
                }
                DataType::Datetime => {
                    if vdata.is_number() {
                        if let Some(v) = vdata.as_i64() {
                            dest.add_datetime(predicate, v);
                        }
                    } else if vdata.is_string() {
                        if let Some(v) = vdata.as_str() {
                            dest.add_datetime_from_str(predicate, v);
                        }
                    }
                }
                DataType::Decimal => {
                    if vdata.is_f64() {
                        if let Some(v) = vdata.as_f64() {
                            dest.add_decimal_from_f64(predicate, v);
                        }
                    } else if vdata.is_number() {
                        if let Some(v) = vdata.as_i64() {
                            dest.add_decimal_from_i64(predicate, v);
                        }
                    } else if vdata.is_string() {
                        if let Some(v) = vdata.as_str() {
                            dest.add_decimal_from_str(predicate, v);
                        }
                    }
                }
                DataType::Boolean => {
                    if let Some(v) = vdata.as_bool() {
                        dest.add_bool(predicate, v);
                    }
                }
                DataType::Binary => {
                    if let Some(v) = vdata.as_str() {
                        dest.add_binary(predicate, v.as_bytes().to_vec());
                    }
                }
            }
        } else {
            error!("json->individual: value for predicate [{}] must contain map", predicate);
            res = false;
        }
    }

    res
}