hit_data/json/
import.rs

1use crate::hit_mod::{Hit, HitKernel, IndexModelImporter};
2use crate::index::IndexEntryProperty;
3use crate::json::utils::*;
4use crate::json::JSONImportError;
5use crate::object_data::{DateTimeUtc, ObjectValue, ObjectValues};
6use chrono::{DateTime, Utc};
7use linked_hash_map::LinkedHashMap;
8use serde_json::Value;
9
10use std::rc::Rc;
11
12use crate::import::generic_import::{finish_import, import_data_object_values};
13
14fn json_to_object_value(value: &Value) -> Result<ObjectValue, JSONImportError> {
15    match value {
16        Value::Null => Ok(ObjectValue::Null),
17        Value::Number(value) => match value.as_f64() {
18            Some(value) => Ok(ObjectValue::F32(value as f32)),
19            None => Err(JSONImportError::InvalidTypeShouldBeANumber()),
20        },
21        Value::String(value) => Ok(ObjectValue::String(String::from(value))),
22        Value::Bool(value) => Ok(ObjectValue::Bool(*value)),
23        Value::Object(value) => {
24            let _type = get_object_property_as_string(value, String::from("type"))?;
25            let sub_value = get_object_property(value, String::from("value"))?;
26            if _type == String::from(JSON_FIELD_TYPE_REFERENCE) {
27                let reference = get_reference(sub_value)?;
28                return Ok(ObjectValue::Reference(reference));
29            } else if _type == String::from(JSON_FIELD_TYPE_REFERENCE_ARRAY) {
30                let array_of_ids = get_array_of_ids(sub_value)?;
31                return Ok(ObjectValue::VecReference(array_of_ids));
32            } else if _type == String::from(JSON_FIELD_TYPE_SUBOBJECT) {
33                let reference = get_reference(sub_value)?;
34                return Ok(ObjectValue::SubObject(reference));
35            } else if _type == String::from(JSON_FIELD_TYPE_SUBOBJECT_ARRAY) {
36                let array_of_ids = get_array_of_ids(sub_value)?;
37                return Ok(ObjectValue::VecSubObjects(array_of_ids));
38            } else if _type == String::from(JSON_FIELD_TYPE_DATE) {
39                let sub_value = get_value_as_string(sub_value)?;
40                let sub_value = DateTime::parse_from_rfc2822(&sub_value);
41                match sub_value {
42                    Ok(sub_value) => Ok(ObjectValue::Date(DateTimeUtc::new(
43                        sub_value.with_timezone(&Utc),
44                    ))),
45                    Err(_error) => Err(JSONImportError::InvalidDateFormat()),
46                }
47            } else {
48                return Err(JSONImportError::InvalidSubObjectType());
49            }
50        }
51        Value::Array(_value) => Err(JSONImportError::ShouldNotBeAnArray()),
52    }
53}
54
55fn get_parent(value: &JSONObject) -> Result<Option<IndexEntryProperty>, JSONImportError> {
56    let parent = get_object_property(value, String::from("parent"))?;
57    match parent {
58        Value::Null => {
59            return Ok(None);
60        }
61        Value::Object(parent) => {
62            let id = get_object_property_as_string(&parent, String::from("id"))?;
63            let property = get_object_property_as_string(&parent, String::from("property"))?;
64            return Ok(Some(IndexEntryProperty {
65                id: id,
66                property: property,
67            }));
68        }
69        _ => return Err(JSONImportError::InvalidTypeShouldBeAnObject()),
70    }
71}
72
73fn import_data<'index>(
74    data: &JSONObject,
75    kernel: Rc<HitKernel>,
76    new_index: &'index mut IndexModelImporter,
77) -> Result<(), JSONImportError> {
78    let id = get_object_property_as_string(data, String::from("id"))?;
79    let model = get_model(kernel, data)?;
80    let parent = get_parent(data)?;
81    let sub_data = get_object_property(data, String::from("data"))?;
82    let sub_data = get_value_as_object(sub_data)?;
83    let mut new_data: ObjectValues = LinkedHashMap::new();
84    for d in sub_data.iter() {
85        new_data.insert(String::from(d.0), json_to_object_value(d.1)?);
86    }
87
88    import_data_object_values(model, id, parent, new_index, new_data)
89        .map_err(JSONImportError::HitError)?;
90
91    return Ok(());
92}
93
94fn get_json_value(value: &String) -> Result<Value, JSONImportError> {
95    match serde_json::from_str(value) {
96        Err(_err) => Err(JSONImportError::InvalidJSON()),
97        Ok(value) => Ok(value),
98    }
99}
100pub fn import_from_string<'a>(
101    value: &String,
102    kernel: Rc<HitKernel>,
103) -> Result<Hit, JSONImportError> {
104    let value = get_json_value(value)?;
105    import(&value, kernel)
106}
107
108pub fn import<'a>(value: &Value, kernel: Rc<HitKernel>) -> Result<Hit, JSONImportError> {
109    let value = get_value_as_object(&value)?;
110    let id = get_object_property_as_string(value, String::from("id"))?;
111    let mut new_index = IndexModelImporter::new(&id, kernel.clone());
112    let data = get_object_property(value, String::from("data"))?;
113    let data = get_value_as_array(data)?;
114    for entry in data.iter() {
115        let clone = kernel.clone();
116        let entry = get_value_as_object(entry)?;
117        import_data(entry, clone, &mut new_index)?;
118    }
119    let new_index = finish_import(new_index, kernel).map_err(JSONImportError::HitError)?;
120    Ok(new_index)
121}