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