1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! Represents 1-N (parent-child) relationships.
//! Each child has a one parent but each parent can have multiple children.
use super::XvcEntity;
use crate::error::{Error, Result};
use crate::{Storable, XvcStore};
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::ops::Deref;
use std::path::Path;

/// Wrapper around XvcEntity that represents a parent-child relationship.
///
/// It represents a parent-child (1-N) relationship between T and U types.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ChildEntity<T: Storable, U: Storable>(XvcEntity, PhantomData<T>, PhantomData<U>);

impl<T: Storable, U: Storable> Storable for ChildEntity<T, U> {
    fn type_description() -> String {
        format!(
            "{}-{}-r1n",
            <T as Storable>::type_description(),
            <U as Storable>::type_description()
        )
    }
}

impl<T: Storable, U: Storable> From<XvcEntity> for ChildEntity<T, U> {
    fn from(xe: XvcEntity) -> Self {
        Self(xe, PhantomData, PhantomData)
    }
}

impl<T: Storable, U: Storable> From<ChildEntity<T, U>> for XvcEntity {
    fn from(r1ne: ChildEntity<T, U>) -> Self {
        r1ne.0
    }
}

impl<T: Storable, U: Storable> Deref for ChildEntity<T, U> {
    type Target = XvcEntity;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

/// RNStore is 1-N RelationStore, where we store one-to-many relationships between two entities.
/// It doesn't have any semantics except binding two entities together.
#[derive(Debug, Clone)]
pub struct R1NStore<T, U>
where
    T: Storable,
    U: Storable,
{
    /// Keeps the parent type
    pub parents: XvcStore<T>,
    /// Keeps the child type
    pub children: XvcStore<U>,
    /// Keeps the relationships between child entities and parent entities
    pub child_parents: XvcStore<ChildEntity<U, T>>,
}

impl<T, U> R1NStore<T, U>
where
    T: Storable,
    U: Storable,
{
    /// Insert a child component to a parent parent_component.
    /// It checks whether the parent is equal to the given, and updates if there is a change.
    pub fn insert(
        &mut self,
        parent_entity: XvcEntity,
        parent_component: T,
        child_entity: XvcEntity,
        child_component: U,
    ) -> Option<XvcEntity> {
        match self.parents.get(&parent_entity) {
            None => {
                self.parents.insert(parent_entity, parent_component);
            }
            Some(value) => {
                if *value != parent_component {
                    self.parents.update(parent_entity, parent_component);
                }
            }
        }

        self.children.insert(child_entity, child_component);
        // CAUTION: The order is reversed!
        self.child_parents
            .insert(child_entity, parent_entity.into())
            .map(XvcEntity::from)
    }

    /// get the store of related entities.
    pub fn children_of(&self, parent_entity: &XvcEntity) -> Result<XvcStore<U>> {
        let related_entities = self.child_parents.iter().filter_map(|(child, parent)| {
            if *parent == (*parent_entity).into() {
                Some(*child)
            } else {
                None
            }
        });
        self.children.subset(related_entities)
    }

    /// Get left entity that's related with thethe right `child_entity`.
    pub fn parent_of(&self, child_entity: &XvcEntity) -> Result<(&ChildEntity<U, T>, &T)> {
        match self.child_parents.get(child_entity) {
            None => Err(Error::NoParentEntityFound {
                entity: (*child_entity).into(),
            }),
            Some(p_e) => {
                let (_, v) =
                    self.parents
                        .get_key_value(&p_e)
                        .ok_or(Error::NoParentEntityFound {
                            entity: (*child_entity).into(),
                        })?;
                Ok((p_e, v))
            }
        }
    }
}

impl<T, U> R1NStore<T, U>
where
    T: Storable,
    U: Storable,
{
    /// Loads the stores from store root and directory named after type names
    pub fn load_r1nstore(store_root: &Path) -> Result<R1NStore<T, U>> {
        let parents = XvcStore::<T>::load_store(store_root)?;
        let children = XvcStore::<U>::load_store(store_root)?;
        let child_parents = XvcStore::<ChildEntity<U, T>>::load_store(store_root)?;

        Ok(R1NStore {
            parents,
            children,
            child_parents,
        })
    }

    /// Records the stores to store root and directories created from type names
    pub fn save_r1nstore(store: &Self, store_root: &Path) -> Result<()> {
        store.parents.save(store_root)?;
        store.children.save(store_root)?;
        store.child_parents.save(store_root)
    }
}