1use super::Environment;
2use crate::{ExpandedDocument, Id, Indexed, IndexedNode, IndexedObject, Node, Object, hash::IndexMap, object};
3use derive_where::derive_where;
4use rdfx::{
5 LocalGenerator,
6 vocabulary::{BlankIdVocabulary, IriVocabulary, VocabularyMut},
7};
8use std::hash::Hash;
9
10#[derive(Clone, Debug, thiserror::Error)]
14#[error("Index `{defined_index}` conflicts with index `{conflicting_index}`")]
15pub struct ConflictingIndexes<T, B> {
16 pub node_id: Id<T, B>,
18 pub defined_index: String,
20 pub conflicting_index: String,
22}
23
24#[derive(Debug, thiserror::Error)]
26pub enum NodeMapError<T, B> {
27 #[error(transparent)]
28 Conflicting(#[from] ConflictingIndexes<T, B>),
30
31 #[error(transparent)]
32 GeneratedId(#[from] crate::id::GeneratedIdError),
34}
35
36pub type Parts<T, B> = (NodeMapGraph<T, B>, IndexMap<Id<T, B>, NodeMapGraph<T, B>>);
41
42#[derive_where(Default)]
50pub struct NodeMap<T, B> {
51 graphs: IndexMap<Id<T, B>, NodeMapGraph<T, B>>,
52 default_graph: NodeMapGraph<T, B>,
53}
54
55impl<T, B> NodeMap<T, B> {
56 #[must_use]
58 pub fn new() -> Self {
59 Self {
60 graphs: IndexMap::default(),
61 default_graph: NodeMapGraph::new(),
62 }
63 }
64
65 #[must_use]
67 pub fn into_parts(self) -> Parts<T, B> {
68 (self.default_graph, self.graphs)
69 }
70
71 #[must_use]
74 pub fn iter(&self) -> Iter<'_, T, B> {
75 Iter {
76 default_graph: Some(&self.default_graph),
77 graphs: self.graphs.iter(),
78 }
79 }
80
81 #[must_use]
83 pub fn iter_named(&self) -> indexmap::map::Iter<'_, Id<T, B>, NodeMapGraph<T, B>> {
84 self.graphs.iter()
85 }
86}
87
88impl<T: Eq + Hash, B: Eq + Hash> NodeMap<T, B> {
89 #[must_use]
92 pub fn graph(&self, id: Option<&Id<T, B>>) -> Option<&NodeMapGraph<T, B>> {
93 match id {
94 Some(id) => self.graphs.get(id),
95 None => Some(&self.default_graph),
96 }
97 }
98
99 pub fn graph_mut(&mut self, id: Option<&Id<T, B>>) -> Option<&mut NodeMapGraph<T, B>> {
101 match id {
102 Some(id) => self.graphs.get_mut(id),
103 None => Some(&mut self.default_graph),
104 }
105 }
106
107 pub fn declare_graph(&mut self, id: Id<T, B>) {
109 if let indexmap::map::Entry::Vacant(entry) = self.graphs.entry(id) {
110 entry.insert(NodeMapGraph::new());
111 }
112 }
113
114 #[must_use]
118 pub fn merge(self) -> NodeMapGraph<T, B>
119 where
120 T: Clone,
121 B: Clone,
122 {
123 let mut result = self.default_graph;
124
125 for (_, graph) in self.graphs {
126 result.merge_with(graph);
127 }
128
129 result
130 }
131}
132
133pub struct Iter<'a, T, B> {
137 default_graph: Option<&'a NodeMapGraph<T, B>>,
138 graphs: indexmap::map::Iter<'a, Id<T, B>, NodeMapGraph<T, B>>,
139}
140
141impl<'a, T, B> Iterator for Iter<'a, T, B> {
142 type Item = (Option<&'a Id<T, B>>, &'a NodeMapGraph<T, B>);
143
144 fn next(&mut self) -> Option<Self::Item> {
145 match self.default_graph.take() {
146 Some(default_graph) => Some((None, default_graph)),
147 None => self.graphs.next().map(|(id, graph)| (Some(id), graph)),
148 }
149 }
150}
151
152impl<'a, T, B> IntoIterator for &'a NodeMap<T, B> {
153 type Item = (Option<&'a Id<T, B>>, &'a NodeMapGraph<T, B>);
154 type IntoIter = Iter<'a, T, B>;
155
156 fn into_iter(self) -> Self::IntoIter {
157 self.iter()
158 }
159}
160
161pub struct IntoIter<T, B> {
165 default_graph: Option<NodeMapGraph<T, B>>,
166 graphs: indexmap::map::IntoIter<Id<T, B>, NodeMapGraph<T, B>>,
167}
168
169impl<T, B> Iterator for IntoIter<T, B> {
170 type Item = (Option<Id<T, B>>, NodeMapGraph<T, B>);
171
172 fn next(&mut self) -> Option<Self::Item> {
173 match self.default_graph.take() {
174 Some(default_graph) => Some((None, default_graph)),
175 None => self.graphs.next().map(|(id, graph)| (Some(id), graph)),
176 }
177 }
178}
179
180impl<T, B> IntoIterator for NodeMap<T, B> {
181 type Item = (Option<Id<T, B>>, NodeMapGraph<T, B>);
182 type IntoIter = IntoIter<T, B>;
183
184 fn into_iter(self) -> Self::IntoIter {
185 IntoIter {
186 default_graph: Some(self.default_graph),
187 graphs: self.graphs.into_iter(),
188 }
189 }
190}
191
192#[derive_where(Default)]
193pub struct NodeMapGraph<T, B> {
197 nodes: IndexMap<Id<T, B>, IndexedNode<T, B>>,
198}
199
200impl<T, B> NodeMapGraph<T, B> {
201 #[must_use]
203 pub fn new() -> Self {
204 Self { nodes: IndexMap::default() }
205 }
206}
207
208pub type DeclareNodeResult<'a, T, B> = Result<&'a mut Indexed<Node<T, B>>, ConflictingIndexes<T, B>>;
210
211impl<T: Eq + Hash, B: Eq + Hash> NodeMapGraph<T, B> {
212 pub fn contains(&self, id: &Id<T, B>) -> bool {
214 self.nodes.contains_key(id)
215 }
216
217 pub fn get(&self, id: &Id<T, B>) -> Option<&IndexedNode<T, B>> {
219 self.nodes.get(id)
220 }
221
222 pub fn get_mut(&mut self, id: &Id<T, B>) -> Option<&mut IndexedNode<T, B>> {
224 self.nodes.get_mut(id)
225 }
226
227 pub fn declare_node(&mut self, id: Id<T, B>, index: Option<&str>) -> DeclareNodeResult<'_, T, B>
234 where
235 T: Clone,
236 B: Clone,
237 {
238 match self.nodes.entry(id) {
239 indexmap::map::Entry::Occupied(occupied) => match (occupied.get().index(), index) {
240 (Some(entry_index), Some(index)) if entry_index != index => Err(ConflictingIndexes {
241 node_id: occupied.key().clone(),
242 defined_index: entry_index.to_string(),
243 conflicting_index: index.to_string(),
244 }),
245 (None, Some(index)) => {
246 let entry = occupied.into_mut();
247 entry.set_index(Some(index.to_owned()));
248 Ok(entry)
249 }
250 _ => Ok(occupied.into_mut()),
251 },
252 indexmap::map::Entry::Vacant(vacant) => {
253 let node = Indexed::new(Node::with_id(vacant.key().clone()), index.map(ToOwned::to_owned));
254 Ok(vacant.insert(node))
255 }
256 }
257 }
258
259 pub fn merge_with(&mut self, other: Self)
263 where
264 T: Clone,
265 B: Clone,
266 {
267 for (_, node) in other {
268 self.merge_node(node);
269 }
270 }
271
272 pub fn merge_node(&mut self, node: IndexedNode<T, B>)
281 where
282 T: Clone,
283 B: Clone,
284 {
285 let (node, index) = node.into_parts();
286
287 if let Some(id) = &node.id {
288 let flat_node = match self.nodes.entry(id.clone()) {
289 indexmap::map::Entry::Occupied(occupied) => {
290 let entry = occupied.into_mut();
291 if let Some(index) = index {
292 entry.set_index(Some(index));
293 }
294 entry
295 }
296 indexmap::map::Entry::Vacant(vacant) => vacant.insert(Indexed::new(Node::with_id(id.clone()), index)),
297 };
298
299 if let Some(types) = node.types {
300 flat_node.types_mut_or_default().extend(types);
301 }
302
303 flat_node.set_graph_entry(node.graph);
304 flat_node.set_included(node.included);
305 flat_node.properties_mut().extend_unique(node.properties);
306
307 if let Some(props) = node.reverse_properties {
308 flat_node.reverse_properties_or_default().extend_unique(props);
309 }
310 }
311 }
312
313 #[must_use]
315 pub fn nodes(&self) -> NodeMapGraphNodes<'_, T, B> {
316 self.nodes.values()
317 }
318
319 #[must_use]
322 pub fn into_nodes(self) -> IntoNodeMapGraphNodes<T, B> {
323 self.nodes.into_values()
324 }
325}
326
327pub type NodeMapGraphNodes<'a, T, B> = indexmap::map::Values<'a, Id<T, B>, IndexedNode<T, B>>;
329pub type IntoNodeMapGraphNodes<T, B> = indexmap::map::IntoValues<Id<T, B>, IndexedNode<T, B>>;
331
332impl<T, B> IntoIterator for NodeMapGraph<T, B> {
333 type Item = (Id<T, B>, IndexedNode<T, B>);
334 type IntoIter = indexmap::map::IntoIter<Id<T, B>, IndexedNode<T, B>>;
335
336 fn into_iter(self) -> Self::IntoIter {
337 self.nodes.into_iter()
338 }
339}
340
341impl<T, B> NodeMapGraph<T, B> {
342 #[must_use]
344 pub fn iter(&self) -> indexmap::map::Iter<'_, Id<T, B>, IndexedNode<T, B>> {
345 self.nodes.iter()
346 }
347}
348
349impl<'a, T, B> IntoIterator for &'a NodeMapGraph<T, B> {
350 type Item = (&'a Id<T, B>, &'a IndexedNode<T, B>);
351 type IntoIter = indexmap::map::Iter<'a, Id<T, B>, IndexedNode<T, B>>;
352
353 fn into_iter(self) -> Self::IntoIter {
354 self.nodes.iter()
355 }
356}
357
358impl<T: Clone + Eq + Hash, B: Clone + Eq + Hash> ExpandedDocument<T, B> {
359 pub fn generate_node_map_with<V: VocabularyMut<Iri = T, BlankId = B>, G: LocalGenerator>(
366 &self,
367 vocabulary: &mut V,
368 generator: G,
369 ) -> Result<NodeMap<T, B>, NodeMapError<T, B>> {
370 let mut node_map: NodeMap<T, B> = NodeMap::new();
371 let mut env: Environment<V, G> = Environment::new(vocabulary, generator);
372 for object in self {
373 extend_node_map(&mut env, &mut node_map, object, None)?;
374 }
375 Ok(node_map)
376 }
377}
378
379pub type ExtendNodeMapResult<V> = Result<
381 IndexedObject<<V as IriVocabulary>::Iri, <V as BlankIdVocabulary>::BlankId>,
382 NodeMapError<<V as IriVocabulary>::Iri, <V as BlankIdVocabulary>::BlankId>,
383>;
384
385fn extend_node_map<N: VocabularyMut, G: LocalGenerator>(
387 env: &mut Environment<N, G>,
388 node_map: &mut NodeMap<N::Iri, N::BlankId>,
389 element: &IndexedObject<N::Iri, N::BlankId>,
390 active_graph: Option<&Id<N::Iri, N::BlankId>>,
391) -> ExtendNodeMapResult<N>
392where
393 N::Iri: Clone + Eq + Hash,
394 N::BlankId: Clone + Eq + Hash,
395{
396 match element.inner() {
397 Object::Value(value) => {
398 let flat_value = value.clone();
399 Ok(Indexed::new(Object::Value(flat_value), element.index().map(ToOwned::to_owned)))
400 }
401 Object::List(list) => {
402 let mut flat_list = Vec::new();
403
404 for item in list {
405 flat_list.push(extend_node_map(env, node_map, item, active_graph)?);
406 }
407
408 Ok(Indexed::new(Object::List(object::List::new(flat_list)), element.index().map(ToOwned::to_owned)))
409 }
410 Object::Node(node) => {
411 let flat_node = extend_node_map_from_node(env, node_map, node, element.index(), active_graph)?;
412 Ok(flat_node.map_inner(Object::node))
413 }
414 }
415}
416
417type ExtendNodeMapFromNodeResult<T, B> = Result<Indexed<Node<T, B>>, NodeMapError<T, B>>;
418
419fn extend_node_map_from_node<N: VocabularyMut, G: LocalGenerator>(
420 env: &mut Environment<N, G>,
421 node_map: &mut NodeMap<N::Iri, N::BlankId>,
422 node: &Node<N::Iri, N::BlankId>,
423 index: Option<&str>,
424 active_graph: Option<&Id<N::Iri, N::BlankId>>,
425) -> ExtendNodeMapFromNodeResult<N::Iri, N::BlankId>
426where
427 N::Iri: Clone + Eq + Hash,
428 N::BlankId: Clone + Eq + Hash,
429{
430 let id = env.assign_node_id(node.id.as_ref())?;
431
432 {
433 let flat_node = unsafe { node_map.graph_mut(active_graph).unwrap_unchecked() }.declare_node(id.clone(), index)?;
436
437 if let Some(entry) = node.types.as_deref() {
438 let types: Result<Vec<_>, _> = entry.iter().map(|ty| env.assign_node_id(Some(ty))).collect();
439 flat_node.types = Some(types?);
440 }
441 }
442
443 if let Some(graph_entry) = node.graph_entry() {
444 node_map.declare_graph(id.clone());
445
446 let mut flat_graph: Vec<_> = Vec::new();
447 for object in graph_entry {
448 let flat_object = extend_node_map(env, node_map, object, Some(&id))?;
449 flat_graph.push(flat_object);
450 }
451
452 let flat_node = unsafe { node_map.graph_mut(active_graph).unwrap_unchecked().get_mut(&id).unwrap_unchecked() };
455 match flat_node.graph_entry_mut() {
456 Some(graph) => graph.extend(flat_graph),
457 None => flat_node.set_graph_entry(Some(flat_graph)),
458 }
459 }
460
461 if let Some(included_entry) = node.included_entry() {
462 for inode in included_entry {
463 extend_node_map_from_node(env, node_map, inode.inner(), inode.index(), active_graph)?;
464 }
465 }
466
467 for (property, objects) in node.properties() {
468 let property = env.assign_node_id(Some(property))?;
472
473 let mut flat_objects = Vec::new();
474 for object in objects {
475 let flat_object = extend_node_map(env, node_map, object, active_graph)?;
476 flat_objects.push(flat_object);
477 }
478 unsafe { node_map.graph_mut(active_graph).unwrap_unchecked().get_mut(&id).unwrap_unchecked() }
480 .properties_mut()
481 .insert_all_unique(property, flat_objects);
482 }
483
484 if let Some(reverse_properties) = node.reverse_properties_entry() {
485 for (property, nodes) in reverse_properties {
486 for subject in nodes {
487 let flat_subject = extend_node_map_from_node(env, node_map, subject.inner(), subject.index(), active_graph)?;
488
489 let subject_id = unsafe { flat_subject.id.as_ref().unwrap_unchecked() };
492
493 let flat_subject = unsafe { node_map.graph_mut(active_graph).unwrap_unchecked().get_mut(subject_id).unwrap_unchecked() };
495
496 flat_subject
497 .properties_mut()
498 .insert_unique(property.clone(), Indexed::none(Object::node(Node::with_id(id.clone()))));
499 }
500 }
501 }
502
503 Ok(Indexed::new(Node::with_id(id), None))
504}