mod private;
use crate::index::{Index, IndexEntryProperty, IndexEntryRef};
use crate::object_data::{ObjectValue, Reference};
use crate::HitError;
pub use private::{get_parent_property_value, mutate_insert_in_ref_array};
pub fn get_parent_index_entry(
index: &Index,
id: &str,
) -> Result<Option<(IndexEntryRef, IndexEntryProperty)>, HitError> {
let entry = index
.index
.get(id)
.ok_or(HitError::IDNotFound(id.to_string(), "get_parent_index_entry".to_string()))?
.borrow();
let parent = entry.get_parent();
match parent {
Some(parent) => Ok(Some(get_parent_index_entry_from_parent(index, parent)?)),
None => Ok(None),
}
}
pub fn get_parent_index_entry_from_parent(
index: &Index,
parent: IndexEntryProperty,
) -> Result<(IndexEntryRef, IndexEntryProperty), HitError> {
match index.index.get(&parent.id) {
Some(entry) => Ok((entry.clone(), parent.clone())),
None => Err(HitError::InvalidParentID(parent.id.to_string())),
}
}
pub fn dispatch_event(index: &Index, id: &str, property: &str) -> Result<(), HitError> {
let entry = index.get(id).ok_or(HitError::IDNotFound(id.to_string(), "dispatch_event".to_string()))?;
let value = entry.borrow().get(&property).clone();
entry.borrow_mut().dispatch_value(&property, value);
Ok(())
}
pub fn mutate_insert_in_reference_array(
data: ObjectValue,
id: &str,
before_id: Option<String>,
) -> Result<Vec<Reference>, HitError> {
match data {
ObjectValue::VecReference(data) => mutate_insert_in_ref_array(data, id, before_id),
ObjectValue::Null => Ok(vec![Reference { id: id.into() }]),
_ => Err(HitError::CannotInsertReferenceInThisDataType()),
}
}
#[cfg(test)]
mod tests {
use linked_hash_map::LinkedHashMap;
use crate::index::{Index, IndexEntryProperty};
use crate::HitError;
use crate::ObjectValue;
fn insert_string_field(
index: &mut Index,
id: &str,
name: &str,
parent: IndexEntryProperty,
) -> Result<(), HitError> {
let mut values = LinkedHashMap::new();
values.insert("name".into(), ObjectValue::String(name.to_string()));
index.insert(id, values, parent, None)
}
fn insert_parent(index: &mut Index, id: &str, name: &str) -> Result<(), HitError> {
let mut values = LinkedHashMap::new();
values.insert("name".into(), ObjectValue::String(name.to_string()));
index.insert_raw(id, values, None)
}
fn insert_sub_field(
index: &mut Index,
name: &str,
id: &str,
_position: u32,
) -> Result<(), HitError> {
insert_string_field(
index,
id,
name,
IndexEntryProperty {
property: "sub_items".to_string(),
id: "id1".to_string(),
},
)
}
fn get_position(index: &Index, id: &str) -> usize {
let parent = index
.get(id)
.expect("should be in the index")
.borrow()
.get_parent()
.expect("should have a parent");
let entry = index.get(&parent.id).expect("parent should exist");
let entry = entry.borrow();
let value = entry.get(&parent.property);
match value {
ObjectValue::VecReference(refs) => refs.iter().position(|r| r.id == id).unwrap(),
ObjectValue::VecSubObjects(refs) => refs.iter().position(|r| r.id == id).unwrap(),
_ => panic!("Invalid value"),
}
}
fn init_index() -> Index {
let mut index = Index::new_for_import(&String::from("id1"));
insert_parent(&mut index, "id1", "Name Of The Model 1").expect("Error");
insert_sub_field(&mut index, "a", "id2", 0).expect("Error");
insert_sub_field(&mut index, "b", "id3", 1).expect("Error");
insert_sub_field(&mut index, "c", "id4", 2).expect("Error");
index
}
#[test]
fn it_should_update_the_positions_when_moving() {
let mut index = init_index();
index
.move_object(
"id4",
IndexEntryProperty {
id: "id1".to_string(),
property: "sub_items".to_string(),
},
Some("id2".to_string()),
)
.expect("move to go ok");
let position = get_position(&index, "id4");
assert_eq!(position, 0);
let position = get_position(&index, "id3");
assert_eq!(position, 2);
}
#[test]
fn it_should_update_the_positions_when_deleting() {
let mut index = init_index();
index.remove_object("id2").expect("should go ok");
let position = get_position(&index, "id4");
assert_eq!(position, 1);
let position = get_position(&index, "id3");
assert_eq!(position, 0);
}
}