1use crate::index::list_helpers::{
2 get_parent_index_entry, get_parent_property_value, mutate_insert_in_reference_array,
3};
4use crate::index::move_object::move_object;
5use crate::index::reference_helpers::remove_reference_from_parent_array_from_property;
6use crate::index::reference_index_helpers::{
7 index_object_references, index_reference, unindex_reference, unindex_reference_from_property,
8};
9use crate::index::remove_helpers::{get_references, remove_object_helper};
10use crate::index::subobject_helpers::insert_subobject_in_array;
11use crate::index::{IndexEntry, IndexEntryProperty, IndexEntryRef};
12use crate::object_data::Id;
13use crate::object_data::ObjectValue;
14use crate::object_data::ObjectValues;
15use crate::object_data::Reference;
16use crate::HitError;
17use std::collections::BTreeMap;
18use std::collections::{btree_map::Iter, HashMap};
19
20use super::{
21 find_references_before_deletion::find_references_recursive,
22 reference_helpers::mutate_remove_from_reference_array,
23};
24
25#[derive(Clone)]
26pub struct Index {
27 pub(in crate) index: BTreeMap<Id, IndexEntryRef>,
28 id: Id,
29}
30
31impl Index {
32 pub fn new_for_import(id: &str) -> Index {
33 Index {
34 index: BTreeMap::new(),
35 id: id.to_string(),
36 }
37 }
38
39 pub fn new(id: &str, values: ObjectValues) -> Result<Index, HitError> {
40 let mut index = Index {
41 index: BTreeMap::new(),
42 id: id.to_string(),
43 };
44 for (_, value) in values.iter() {
46 match value {
47 ObjectValue::Reference(_) => {
48 return Err(HitError::CanOnlySetScalarValuesInInsertedObject())
49 }
50 ObjectValue::VecReference(_) => {
51 return Err(HitError::CanOnlySetScalarValuesInInsertedObject())
52 }
53 ObjectValue::SubObject(_) => {
54 return Err(HitError::CanOnlySetScalarValuesInInsertedObject())
55 }
56 ObjectValue::VecSubObjects(_) => {
57 return Err(HitError::CanOnlySetScalarValuesInInsertedObject())
58 }
59 _ => {}
60 }
61 }
62 index.insert_raw(id, values, None)?;
63 Ok(index)
64 }
65
66 pub fn get_main_object_id(&self) -> &Id {
67 return &self.id;
68 }
69
70 pub fn get(&self, id: &str) -> Option<IndexEntryRef> {
71 match self.index.get(id) {
72 Some(entry) => Some(entry.clone()),
73 None => None,
74 }
75 }
76
77 pub fn get_mut(&mut self, id: &str) -> Option<&mut IndexEntryRef> {
78 return self.index.get_mut(id);
79 }
80
81 pub fn get_value(&self, id: &str, property: &str) -> Option<ObjectValue> {
82 let obj = self.get(id)?;
83 let obj = obj.borrow();
84 let value = obj.get(&property);
85 Some(value.clone())
86 }
87
88 pub fn set_value(
89 &mut self,
90 id: &str,
91 property: &str,
92 value: ObjectValue,
93 ) -> Result<(), HitError> {
94 unindex_reference_from_property(self, id, property)?;
97
98 match value.clone() {
99 ObjectValue::Null => {}
100 ObjectValue::Bool(_) => {}
101 ObjectValue::Date(_) => {}
102 ObjectValue::F32(_) => {}
103 ObjectValue::Reference(value) => {
104 index_reference(self, &value, property, id)?;
105 }
106 ObjectValue::String(_) => {}
107 _ => return Err(HitError::CanOnlySetScalarValues()),
108 }
109
110 let entry = self.get(id).ok_or(HitError::IDNotFound(id.to_string(), "set_value".into()))?;
111 entry.borrow_mut().set(property, value)?;
112 Ok(())
113 }
114
115 pub fn iter(&self) -> Iter<Id, IndexEntryRef> {
116 return self.index.iter();
117 }
118
119 pub fn contains(&self, id: &str) -> bool {
120 return self.index.contains_key(id);
121 }
122
123 pub fn insert(
124 &mut self,
125 id: &str,
126 values: ObjectValues,
127 parent: IndexEntryProperty,
128 before_id: Option<String>,
129 ) -> Result<(), HitError> {
130 self.insert_quietly(id, values, parent, before_id)?;
131 let (entry, parent) =
133 get_parent_index_entry(self, &id)?.ok_or(HitError::InvalidParentID(id.to_string()))?;
134 Index::dispatch_value_property(entry, &parent.property);
135 Ok(())
136 }
137
138 pub(in crate::index) fn insert_raw(
142 &mut self,
143 id: &str,
144 values: ObjectValues,
145 parent: Option<IndexEntryProperty>,
146 ) -> Result<(), HitError> {
147 if self.index.contains_key(id) {
149 return Err(HitError::DuplicateID(id.to_string()));
150 }
151 self.index.insert(
152 id.to_string(),
153 IndexEntry::new(id.to_string(), values, parent.clone()),
154 );
155 Ok(())
156 }
157
158 fn insert_quietly(
159 &mut self,
160 id: &str,
161 values: ObjectValues,
162 parent: IndexEntryProperty,
163 before_id: Option<String>,
164 ) -> Result<(), HitError> {
165 self.insert_raw(id, values.clone(), Some(parent.clone()))?;
167
168 index_object_references(self, values, id)?;
170
171 insert_subobject_in_array(self, parent, id, before_id)?;
173
174 Ok(())
175 }
176
177 pub fn move_reference(
178 &mut self,
179 id: &str,
180 target: IndexEntryProperty,
181 before_id: Option<Id>,
182 ) -> Result<(), HitError> {
183 let target_entry = {
184 self.get_mut(&target.id)
185 .ok_or(HitError::IDNotFound(target.id.to_string(), "move_reference".into()))?
186 };
187 let data = get_parent_property_value(&target_entry, &target);
188
189 match &data {
191 ObjectValue::VecReference(data) => {
192 if !data.iter().any(|r| r.id == id) {
193 return Err(HitError::ReferenceNotFound());
194 }
195 match &before_id {
196 Some(before_id) => {
197 if !data.iter().any(|r| r.id == id) {
198 return Err(HitError::InvalidBeforeId(before_id.clone()));
199 }
200 }
201 None => {}
202 }
203 }
204 ObjectValue::Null => {
205 return Err(HitError::ReferenceNotFound());
206 }
207 _ => return Err(HitError::CannotInsertReferenceInThisDataType()),
208 }
209
210 let data = mutate_remove_from_reference_array(data, id)?.unwrap_or(vec![]);
211 let data =
212 mutate_insert_in_reference_array(ObjectValue::VecReference(data), id, before_id)?;
213 target_entry.borrow_mut().data.insert(
215 target.clone().property,
216 ObjectValue::VecReference(data.clone()),
217 );
218
219 Index::dispatch_value(
220 target_entry.clone(),
221 &target.property,
222 ObjectValue::VecReference(data),
223 );
224 Ok(())
225 }
226
227 pub fn insert_reference(
228 &mut self,
229 id: &str,
230 target: IndexEntryProperty,
231 before_id: Option<Id>,
232 ) -> Result<(), HitError> {
233 {
234 let target_entry = {
235 self.get_mut(&target.id)
236 .ok_or(HitError::IDNotFound(target.id.to_string(), "insert_reference".into()))?
237 };
238 let data = get_parent_property_value(&target_entry, &target);
239
240 match &data {
241 ObjectValue::VecReference(data) => {
242 }
247 ObjectValue::Null => {}
248 _ => return Err(HitError::CannotInsertReferenceInThisDataType()),
249 }
250
251 let data = mutate_insert_in_reference_array(data, id, before_id)?;
253 let value = ObjectValue::VecReference(data);
254
255 target_entry
257 .borrow_mut()
258 .data
259 .insert(target.clone().property, value.clone());
260 }
261
262 index_reference(
264 self,
265 &Reference { id: id.to_string() },
266 &target.property,
267 &target.id,
268 )?;
269 {
271 let target_entry = {
272 self.get_mut(&target.id)
273 .ok_or(HitError::IDNotFound(target.id.to_string(), "insert_reference".into()))?
274 };
275 let data = get_parent_property_value(&target_entry, &target);
276 Index::dispatch_value(target_entry.clone(), &target.property, data);
277 }
278
279 Ok(())
280 }
281
282 pub fn remove_reference(
283 &mut self,
284 id: &str,
285 parent: IndexEntryProperty,
286 ) -> Result<(), HitError> {
287 let value = remove_reference_from_parent_array_from_property(self, parent.clone(), id)?;
288
289 unindex_reference(self, parent.clone(), id)?;
290 let entry = self
292 .get(&parent.clone().id)
293 .ok_or(HitError::IDNotFound(parent.clone().id.to_string(), "remove_reference".into()))?;
294 Index::dispatch_value(entry, &parent.property, value);
295 Ok(())
296 }
297
298 pub(in crate) fn get_references(&self, id: &str) -> Result<Vec<IndexEntryProperty>, HitError> {
299 get_references(&self, id)
300 }
301
302 pub fn find_references_recursive(
303 &self,
304 id: &str,
305 ) -> Result<(HashMap<String, Vec<IndexEntryProperty>>, Vec<String>), HitError> {
306 find_references_recursive(self, id)
307 }
308
309 pub fn remove_object(&mut self, id: &str) -> Result<Vec<String>, HitError> {
310 let (parent_entry, parent) =
311 get_parent_index_entry(self, &id)?.ok_or(HitError::CannotDeleteRootObject())?;
312
313 let (refs, id_list) = find_references_recursive(self, id)?;
314 if refs.len() > 0 {
315 return Err(HitError::CannotDeleteObjectWithReferences(refs));
316 }
317 remove_object_helper(self, id)?;
318
319 Index::dispatch_value_property(parent_entry, &parent.property);
321 Ok(id_list)
322 }
323
324 pub fn move_object(
325 &mut self,
326 id: &str,
327 property: IndexEntryProperty,
328 before_id: Option<String>,
329 ) -> Result<(), HitError> {
330 move_object(self, id, property, before_id)
331 }
332
333 fn dispatch_value_property(entry: IndexEntryRef, property: &str) {
334 let value = entry.borrow().get(property).clone();
335 Index::dispatch_value(entry, property, value)
336 }
337
338 fn dispatch_value(entry: IndexEntryRef, property: &str, value: ObjectValue) {
339 entry.borrow_mut().dispatch_value(property, value);
340 }
341}
342
343#[cfg(test)]
344mod tests {
345 use linked_hash_map::LinkedHashMap;
346
347 use crate::index::Index;
348 use crate::HitError;
349 use crate::ObjectValue;
350 use crate::Reference;
351
352 #[test]
353 fn it_should_create_a_new_index_with_values() {
354 let mut values = LinkedHashMap::new();
355 values.insert("test".into(), ObjectValue::Bool(true));
356 values.insert("testString".into(), ObjectValue::String("value".into()));
357 assert!(Index::new("id", values).is_ok());
358 }
359
360 #[test]
361 fn it_should_fail_creating_a_new_index_with_reference_values() {
362 let mut values = LinkedHashMap::new();
363 values.insert(
364 "reference".into(),
365 ObjectValue::Reference(Reference { id: "a".into() }),
366 );
367 assert!(matches!(
368 Index::new("id", values).err(),
369 Some(HitError::CanOnlySetScalarValuesInInsertedObject())
370 ));
371 }
372
373 #[test]
374 fn it_should_fail_creating_a_new_index_with_reference_array_values() {
375 let mut values = LinkedHashMap::new();
376 values.insert(
377 "reference".into(),
378 ObjectValue::VecReference(vec![Reference { id: "a".into() }]),
379 );
380 assert!(matches!(
381 Index::new("id", values).err(),
382 Some(HitError::CanOnlySetScalarValuesInInsertedObject())
383 ));
384 }
385 #[test]
386 fn it_should_fail_creating_a_new_index_with_subobject_values() {
387 let mut values = LinkedHashMap::new();
388 values.insert(
389 "reference".into(),
390 ObjectValue::SubObject(Reference { id: "a".into() }),
391 );
392 assert!(Index::new("id", values).is_err());
393 }
394 #[test]
395 fn it_should_fail_creating_a_new_index_with_subobject_array_values() {
396 let mut values = LinkedHashMap::new();
397 values.insert(
398 "reference".into(),
399 ObjectValue::VecSubObjects(vec![Reference { id: "a".into() }]),
400 );
401 assert!(Index::new("id", values).is_err());
402 }
403
404 #[test]
405 fn it_should_get_existing_data() {
406 let mut values = LinkedHashMap::new();
407 values.insert("test".into(), ObjectValue::Bool(true));
408 let index = Index::new("id", values).ok().unwrap();
409
410 let item = index.get("id").unwrap();
411 let item = item.borrow();
412
413 let prop = item.get("test");
414 match prop {
415 ObjectValue::Bool(value) => {
416 assert_eq!(value, &true);
417 }
418 _ => panic!("Should be a boolean"),
419 }
420 }
421}