1use super::*;
2
3#[allow(clippy::derive_hash_xor_eq)]
5#[derive(Clone, Debug, Getters, MutGetters, Hash)]
6#[getset(get = "pub", get_mut = "pub")]
7pub struct CibouletteResourceType {
8 relationships: BTreeMap<ArcStr, petgraph::graph::EdgeIndex<u16>>,
9 relationships_type_to_alias: BTreeMap<ArcStr, ArcStr>,
10 schema: MessyJsonObject,
11 ids: CibouletteIdTypeSelector,
12 name: ArcStr,
13}
14
15#[derive(Clone, Debug, Getters, MutGetters, Ord, PartialEq, PartialOrd, Eq, Hash)]
17#[getset(get = "pub", get_mut = "pub")]
18pub struct CibouletteResourceRelationshipDetails {
19 relation_alias: ArcStr,
20 related_type: Arc<CibouletteResourceType>,
21 relation_option: CibouletteRelationshipOption,
22}
23
24impl CibouletteResourceType {
25 pub(crate) fn new(
27 name: ArcStr,
28 ids: CibouletteIdTypeSelector,
29 schema: MessyJsonObject,
30 ) -> Self {
31 CibouletteResourceType {
32 relationships: BTreeMap::new(),
33 relationships_type_to_alias: BTreeMap::new(),
34 schema,
35 ids,
36 name,
37 }
38 }
39
40 pub fn get_alias(&self, name: &str) -> Result<&ArcStr, CibouletteError> {
42 self.relationships_type_to_alias().get(name).ok_or_else(|| {
43 CibouletteError::MissingAliasTranslation(self.name().to_string(), name.to_string())
44 })
45 }
46
47 pub fn get_relationship_with_alias(
49 &self,
50 store: &CibouletteStore,
51 alias: &str,
52 ) -> Result<(ArcStr, Arc<CibouletteResourceType>), CibouletteError> {
53 let (alias, edge_index) = self.relationships().get_key_value(alias).ok_or_else(|| {
54 CibouletteError::UnknownRelationship(self.name().to_string(), alias.to_string())
55 })?;
56 let self_index = *store
57 .map()
58 .get(self.name().as_str())
59 .ok_or_else(|| CibouletteError::UnknownType(self.name().to_string()))?;
60 let (t1, t2) = store.graph().edge_endpoints(*edge_index).ok_or_else(|| {
61 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
62 })?;
63 Ok((
64 alias.clone(),
65 match t1 == self_index {
66 true => store.graph().node_weight(t2).cloned().ok_or_else(|| {
67 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
68 })?,
69 false => store.graph().node_weight(t1).cloned().ok_or_else(|| {
70 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
71 })?,
72 },
73 ))
74 }
75
76 pub fn get_relationship(
78 &self,
79 store: &CibouletteStore,
80 alias: &str,
81 ) -> Result<Arc<CibouletteResourceType>, CibouletteError> {
82 let edge_index = self.relationships().get(alias).ok_or_else(|| {
83 CibouletteError::UnknownRelationship(self.name().to_string(), alias.to_string())
84 })?;
85 let self_index = *store
86 .map()
87 .get(self.name().as_str())
88 .ok_or_else(|| CibouletteError::UnknownType(self.name().to_string()))?;
89 let (t1, t2) = store.graph().edge_endpoints(*edge_index).ok_or_else(|| {
90 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
91 })?;
92 Ok(match t1 == self_index {
93 true => store.graph().node_weight(t2).cloned().ok_or_else(|| {
94 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
95 })?,
96 false => store.graph().node_weight(t1).cloned().ok_or_else(|| {
97 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
98 })?,
99 })
100 }
101
102 pub fn get_relationship_details(
104 &self,
105 store: &CibouletteStore,
106 alias: &str,
107 ) -> Result<CibouletteResourceRelationshipDetails, CibouletteError> {
108 let (edge_alias, edge_index) =
109 self.relationships().get_key_value(alias).ok_or_else(|| {
110 CibouletteError::UnknownRelationship(self.name().to_string(), alias.to_string())
111 })?;
112 let self_index = *store
113 .map()
114 .get(self.name().as_str())
115 .ok_or_else(|| CibouletteError::UnknownType(self.name().to_string()))?;
116 let rel_weight = store
117 .graph()
118 .edge_weight(*edge_index)
119 .ok_or_else(|| {
120 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
121 })?
122 .clone();
123 let (t1, t2) = store.graph().edge_endpoints(*edge_index).ok_or_else(|| {
124 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
125 })?;
126 let related_type = match t1 == self_index {
127 true => store.graph().node_weight(t2).cloned().ok_or_else(|| {
128 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
129 })?,
130 false => store.graph().node_weight(t1).cloned().ok_or_else(|| {
131 CibouletteError::RelNotInGraph(self.name().to_string(), alias.to_string())
132 })?,
133 };
134 Ok(CibouletteResourceRelationshipDetails {
135 relation_alias: edge_alias.clone(),
136 related_type,
137 relation_option: rel_weight,
138 })
139 }
140
141 pub fn has_fields<'store, I>(&self, fields: I) -> Result<Option<String>, CibouletteError>
143 where
144 I: Iterator<Item = &'store str>,
145 {
146 Ok(fields
147 .into_iter()
148 .find_map(|k| match self.schema.has_field(k) {
149 true => None,
150 false => Some(k.to_string()),
151 }))
152 }
153}
154
155impl Ord for CibouletteResourceType {
156 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
157 self.name.cmp(&other.name)
158 }
159}
160
161impl PartialOrd for CibouletteResourceType {
162 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
163 Some(self.name.cmp(&other.name))
164 }
165}
166
167impl PartialEq for CibouletteResourceType {
168 fn eq(&self, other: &Self) -> bool {
169 self.name == other.name
170 }
171}
172
173impl Eq for CibouletteResourceType {}