1use std::{
16 fmt::{Display, Formatter},
17 sync::Arc,
18};
19
20use crate::evaluation::variable_value::VariableValue;
21
22use super::{ElementPropertyMap, ElementValue};
23
24#[derive(Debug, Clone, Hash, PartialEq, Eq)]
25pub struct ElementReference {
26 pub source_id: Arc<str>,
27 pub element_id: Arc<str>,
28}
29
30impl ElementReference {
31 pub fn new(source_id: &str, element_id: &str) -> Self {
32 ElementReference {
33 source_id: Arc::from(source_id),
34 element_id: Arc::from(element_id),
35 }
36 }
37}
38
39impl Display for ElementReference {
40 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
41 write!(f, "{}:{}", self.source_id, self.element_id)
42 }
43}
44
45pub type ElementTimestamp = u64;
46
47#[derive(Debug, Clone, Hash, PartialEq, Eq)]
48pub struct ElementMetadata {
49 pub reference: ElementReference,
50 pub labels: Arc<[Arc<str>]>,
51 pub effective_from: ElementTimestamp,
52}
53
54impl Display for ElementMetadata {
55 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
56 write!(
57 f,
58 "({}, [{}], {})",
59 self.reference,
60 self.labels.join(","),
61 self.effective_from
62 )
63 }
64}
65
66#[derive(Debug, Clone, Hash, Eq, PartialEq)]
67pub enum Element {
68 Node {
70 metadata: ElementMetadata,
71 properties: ElementPropertyMap,
72 },
73 Relation {
74 metadata: ElementMetadata,
75 in_node: ElementReference,
76 out_node: ElementReference,
77 properties: ElementPropertyMap,
78 },
79}
80
81impl Element {
82 pub fn get_reference(&self) -> &ElementReference {
83 match self {
84 Element::Node { metadata, .. } => &metadata.reference,
85 Element::Relation { metadata, .. } => &metadata.reference,
86 }
87 }
88
89 pub fn get_effective_from(&self) -> ElementTimestamp {
90 match self {
91 Element::Node { metadata, .. } => metadata.effective_from,
92 Element::Relation { metadata, .. } => metadata.effective_from,
93 }
94 }
95
96 pub fn get_metadata(&self) -> &ElementMetadata {
97 match self {
98 Element::Node { metadata, .. } => metadata,
99 Element::Relation { metadata, .. } => metadata,
100 }
101 }
102
103 pub fn get_property(&self, name: &str) -> &ElementValue {
104 let props = match self {
105 Element::Node { properties, .. } => properties,
106 Element::Relation { properties, .. } => properties,
107 };
108 &props[name]
109 }
110
111 pub fn get_properties(&self) -> &ElementPropertyMap {
112 match self {
113 Element::Node { properties, .. } => properties,
114 Element::Relation { properties, .. } => properties,
115 }
116 }
117
118 pub fn merge_missing_properties(&mut self, other: &Element) {
119 match (self, other) {
120 (
121 Element::Node {
122 properties,
123 metadata,
124 },
125 Element::Node {
126 properties: other_properties,
127 metadata: other_metadata,
128 },
129 ) => {
130 assert_eq!(metadata.reference, other_metadata.reference);
131 properties.merge(other_properties);
132 }
133 (
134 Element::Relation {
135 in_node: _,
136 out_node: _,
137 properties,
138 metadata,
139 },
140 Element::Relation {
141 in_node: _other_in_node,
142 out_node: _other_out_node,
143 properties: other_properties,
144 metadata: other_metadata,
145 },
146 ) => {
147 assert_eq!(metadata.reference, other_metadata.reference);
148 properties.merge(other_properties);
149 }
150 _ => panic!("Cannot merge different element types"),
151 }
152 }
153
154 pub fn to_expression_variable(&self) -> VariableValue {
155 VariableValue::Element(Arc::new(self.clone()))
156 }
157
158 pub fn update_effective_time(&mut self, timestamp: ElementTimestamp) {
159 match self {
160 Element::Node { metadata, .. } => metadata.effective_from = timestamp,
161 Element::Relation { metadata, .. } => metadata.effective_from = timestamp,
162 }
163 }
164}
165
166impl From<&Element> for serde_json::Value {
167 fn from(val: &Element) -> Self {
168 match val {
169 Element::Node {
170 metadata,
171 properties,
172 } => {
173 let mut properties: serde_json::Map<String, serde_json::Value> = properties.into();
174
175 properties.insert(
176 "$metadata".to_string(),
177 serde_json::Value::String(metadata.to_string()),
178 );
179
180 serde_json::Value::Object(properties)
181 }
182 Element::Relation {
183 metadata,
184 in_node,
185 out_node,
186 properties,
187 } => {
188 let mut properties: serde_json::Map<String, serde_json::Value> = properties.into();
189
190 properties.insert(
191 "$metadata".to_string(),
192 serde_json::Value::String(metadata.to_string()),
193 );
194
195 properties.insert(
196 "$in_node".to_string(),
197 serde_json::Value::String(in_node.to_string()),
198 );
199 properties.insert(
200 "$out_node".to_string(),
201 serde_json::Value::String(out_node.to_string()),
202 );
203
204 serde_json::Value::Object(properties)
205 }
206 }
207 }
208}