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