Skip to main content

jellyflow_core/core/model/
graph.rs

1use std::borrow::Borrow;
2use std::collections::{BTreeMap, btree_map};
3use std::iter::FusedIterator;
4use std::ops::Index;
5
6use serde::{Deserialize, Serialize};
7
8use crate::core::ids::{
9    BindingId, EdgeId, GraphId, GroupId, NodeId, PortId, StickyNoteId, SymbolId,
10};
11use crate::core::imports::GraphImport;
12
13use super::binding::Binding;
14use super::edge::Edge;
15use super::node::Node;
16use super::port::Port;
17use super::resources::{Group, StickyNote, Symbol};
18
19/// Graph schema version (v1).
20pub const GRAPH_VERSION: u32 = 1;
21
22/// Read-only view over one graph element collection.
23///
24/// This keeps `Graph`'s public API from committing callers to its storage type while preserving the
25/// common map-like read operations adapters need for deterministic traversal and lookup.
26#[derive(Debug, Clone, Copy)]
27pub struct GraphElements<'a, K, V> {
28    entries: &'a BTreeMap<K, V>,
29}
30
31/// Iterator over graph element ids and values.
32#[derive(Debug, Clone)]
33pub struct GraphElementIter<'a, K, V> {
34    inner: btree_map::Iter<'a, K, V>,
35}
36
37/// Iterator over graph element ids.
38#[derive(Debug, Clone)]
39pub struct GraphElementKeys<'a, K, V> {
40    inner: btree_map::Keys<'a, K, V>,
41}
42
43/// Iterator over graph element values.
44#[derive(Debug, Clone)]
45pub struct GraphElementValues<'a, K, V> {
46    inner: btree_map::Values<'a, K, V>,
47}
48
49impl<'a, K, V> GraphElements<'a, K, V> {
50    pub(crate) fn new(entries: &'a BTreeMap<K, V>) -> Self {
51        Self { entries }
52    }
53
54    /// Returns the number of elements.
55    pub fn len(&self) -> usize {
56        self.entries.len()
57    }
58
59    /// Returns `true` when this collection has no elements.
60    pub fn is_empty(&self) -> bool {
61        self.entries.is_empty()
62    }
63
64    /// Returns `true` when the collection contains `key`.
65    pub fn contains_key<Q>(&self, key: &Q) -> bool
66    where
67        K: Borrow<Q> + Ord,
68        Q: Ord + ?Sized,
69    {
70        self.entries.contains_key(key)
71    }
72
73    /// Returns an element by id.
74    pub fn get<Q>(&self, key: &Q) -> Option<&'a V>
75    where
76        K: Borrow<Q> + Ord,
77        Q: Ord + ?Sized,
78    {
79        self.entries.get(key)
80    }
81
82    /// Returns key-value pairs in deterministic id order.
83    pub fn iter(&self) -> GraphElementIter<'a, K, V> {
84        GraphElementIter {
85            inner: self.entries.iter(),
86        }
87    }
88
89    /// Returns ids in deterministic order.
90    pub fn keys(&self) -> GraphElementKeys<'a, K, V> {
91        GraphElementKeys {
92            inner: self.entries.keys(),
93        }
94    }
95
96    /// Returns element values in deterministic id order.
97    pub fn values(&self) -> GraphElementValues<'a, K, V> {
98        GraphElementValues {
99            inner: self.entries.values(),
100        }
101    }
102}
103
104impl<'a, 'b, K, V> PartialEq<GraphElements<'b, K, V>> for GraphElements<'a, K, V>
105where
106    K: Ord + PartialEq,
107    V: PartialEq,
108{
109    fn eq(&self, other: &GraphElements<'b, K, V>) -> bool {
110        self.entries == other.entries
111    }
112}
113
114impl<'a, K, V> Eq for GraphElements<'a, K, V>
115where
116    K: Ord + Eq,
117    V: Eq,
118{
119}
120
121impl<'a, K, V> Index<&K> for GraphElements<'a, K, V>
122where
123    K: Ord,
124{
125    type Output = V;
126
127    fn index(&self, key: &K) -> &Self::Output {
128        self.entries.get(key).expect("no entry found for key")
129    }
130}
131
132impl<'a, K, V> IntoIterator for GraphElements<'a, K, V> {
133    type Item = (&'a K, &'a V);
134    type IntoIter = GraphElementIter<'a, K, V>;
135
136    fn into_iter(self) -> Self::IntoIter {
137        self.iter()
138    }
139}
140
141impl<'a, K, V> Iterator for GraphElementIter<'a, K, V> {
142    type Item = (&'a K, &'a V);
143
144    fn next(&mut self) -> Option<Self::Item> {
145        self.inner.next()
146    }
147
148    fn size_hint(&self) -> (usize, Option<usize>) {
149        self.inner.size_hint()
150    }
151}
152
153impl<'a, K, V> DoubleEndedIterator for GraphElementIter<'a, K, V> {
154    fn next_back(&mut self) -> Option<Self::Item> {
155        self.inner.next_back()
156    }
157}
158
159impl<'a, K, V> ExactSizeIterator for GraphElementIter<'a, K, V> {}
160impl<'a, K, V> FusedIterator for GraphElementIter<'a, K, V> {}
161
162impl<'a, K, V> Iterator for GraphElementKeys<'a, K, V> {
163    type Item = &'a K;
164
165    fn next(&mut self) -> Option<Self::Item> {
166        self.inner.next()
167    }
168
169    fn size_hint(&self) -> (usize, Option<usize>) {
170        self.inner.size_hint()
171    }
172}
173
174impl<'a, K, V> DoubleEndedIterator for GraphElementKeys<'a, K, V> {
175    fn next_back(&mut self) -> Option<Self::Item> {
176        self.inner.next_back()
177    }
178}
179
180impl<'a, K, V> ExactSizeIterator for GraphElementKeys<'a, K, V> {}
181impl<'a, K, V> FusedIterator for GraphElementKeys<'a, K, V> {}
182
183impl<'a, K, V> Iterator for GraphElementValues<'a, K, V> {
184    type Item = &'a V;
185
186    fn next(&mut self) -> Option<Self::Item> {
187        self.inner.next()
188    }
189
190    fn size_hint(&self) -> (usize, Option<usize>) {
191        self.inner.size_hint()
192    }
193}
194
195impl<'a, K, V> DoubleEndedIterator for GraphElementValues<'a, K, V> {
196    fn next_back(&mut self) -> Option<Self::Item> {
197        self.inner.next_back()
198    }
199}
200
201impl<'a, K, V> ExactSizeIterator for GraphElementValues<'a, K, V> {}
202impl<'a, K, V> FusedIterator for GraphElementValues<'a, K, V> {}
203
204/// Node graph document.
205#[derive(Debug, Clone, Serialize, Deserialize)]
206pub struct Graph {
207    /// Stable identity for editor-state lookup and cross-graph references.
208    graph_id: GraphId,
209    /// Schema version for migrations.
210    graph_version: u32,
211
212    /// Transitive graph dependencies (semantic subgraphs / libraries).
213    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
214    pub(crate) imports: BTreeMap<GraphId, GraphImport>,
215
216    /// Graph-scoped symbols (blackboard/variables).
217    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
218    pub(crate) symbols: BTreeMap<SymbolId, Symbol>,
219
220    /// Node instances.
221    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
222    pub(crate) nodes: BTreeMap<NodeId, Node>,
223
224    /// Port instances (owned by nodes, but stored in a flat map for stable lookup).
225    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
226    pub(crate) ports: BTreeMap<PortId, Port>,
227
228    /// Edges between ports.
229    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
230    pub(crate) edges: BTreeMap<EdgeId, Edge>,
231
232    /// Optional groups.
233    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
234    pub(crate) groups: BTreeMap<GroupId, Group>,
235
236    /// Optional sticky notes.
237    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
238    pub(crate) sticky_notes: BTreeMap<StickyNoteId, StickyNote>,
239
240    /// Optional knowledge-canvas bindings.
241    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
242    pub(crate) bindings: BTreeMap<BindingId, Binding>,
243}
244
245impl Default for Graph {
246    fn default() -> Self {
247        Self::new(GraphId::new())
248    }
249}
250
251impl Graph {
252    /// Creates a new, empty graph with the given id.
253    pub fn new(graph_id: GraphId) -> Self {
254        Self {
255            graph_id,
256            graph_version: GRAPH_VERSION,
257            imports: BTreeMap::new(),
258            symbols: BTreeMap::new(),
259            nodes: BTreeMap::new(),
260            ports: BTreeMap::new(),
261            edges: BTreeMap::new(),
262            groups: BTreeMap::new(),
263            sticky_notes: BTreeMap::new(),
264            bindings: BTreeMap::new(),
265        }
266    }
267
268    /// Returns the stable graph identity.
269    pub fn graph_id(&self) -> GraphId {
270        self.graph_id
271    }
272
273    /// Returns the schema version.
274    pub fn graph_version(&self) -> u32 {
275        self.graph_version
276    }
277
278    /// Returns graph imports.
279    pub fn imports(&self) -> GraphElements<'_, GraphId, GraphImport> {
280        GraphElements::new(&self.imports)
281    }
282
283    /// Returns one graph import.
284    pub fn import(&self, id: &GraphId) -> Option<&GraphImport> {
285        self.imports.get(id)
286    }
287
288    /// Returns one mutable graph import.
289    pub(crate) fn import_mut(&mut self, id: &GraphId) -> Option<&mut GraphImport> {
290        self.imports.get_mut(id)
291    }
292
293    /// Updates one graph import through a controlled mutable callback.
294    pub(crate) fn update_import<R>(
295        &mut self,
296        id: &GraphId,
297        f: impl FnOnce(&mut GraphImport) -> R,
298    ) -> Option<R> {
299        self.imports.get_mut(id).map(f)
300    }
301
302    /// Inserts or replaces a graph import.
303    pub(crate) fn insert_import(&mut self, id: GraphId, value: GraphImport) -> Option<GraphImport> {
304        self.imports.insert(id, value)
305    }
306
307    /// Removes a graph import.
308    pub(crate) fn remove_import(&mut self, id: &GraphId) -> Option<GraphImport> {
309        self.imports.remove(id)
310    }
311
312    /// Clears all graph imports.
313    pub(crate) fn clear_imports(&mut self) {
314        self.imports.clear();
315    }
316
317    /// Retains graph imports matching `f`.
318    pub(crate) fn retain_imports(&mut self, f: impl FnMut(&GraphId, &mut GraphImport) -> bool) {
319        self.imports.retain(f);
320    }
321
322    /// Returns graph symbols.
323    pub fn symbols(&self) -> GraphElements<'_, SymbolId, Symbol> {
324        GraphElements::new(&self.symbols)
325    }
326
327    /// Returns one symbol.
328    pub fn symbol(&self, id: &SymbolId) -> Option<&Symbol> {
329        self.symbols.get(id)
330    }
331
332    /// Returns one mutable symbol.
333    pub(crate) fn symbol_mut(&mut self, id: &SymbolId) -> Option<&mut Symbol> {
334        self.symbols.get_mut(id)
335    }
336
337    /// Updates one symbol through a controlled mutable callback.
338    pub(crate) fn update_symbol<R>(
339        &mut self,
340        id: &SymbolId,
341        f: impl FnOnce(&mut Symbol) -> R,
342    ) -> Option<R> {
343        self.symbols.get_mut(id).map(f)
344    }
345
346    /// Inserts or replaces a symbol.
347    pub(crate) fn insert_symbol(&mut self, id: SymbolId, value: Symbol) -> Option<Symbol> {
348        self.symbols.insert(id, value)
349    }
350
351    /// Removes a symbol.
352    pub(crate) fn remove_symbol(&mut self, id: &SymbolId) -> Option<Symbol> {
353        self.symbols.remove(id)
354    }
355
356    /// Clears all graph symbols.
357    pub(crate) fn clear_symbols(&mut self) {
358        self.symbols.clear();
359    }
360
361    /// Retains graph symbols matching `f`.
362    pub(crate) fn retain_symbols(&mut self, f: impl FnMut(&SymbolId, &mut Symbol) -> bool) {
363        self.symbols.retain(f);
364    }
365
366    /// Returns graph nodes.
367    pub fn nodes(&self) -> GraphElements<'_, NodeId, Node> {
368        GraphElements::new(&self.nodes)
369    }
370
371    /// Returns one node.
372    pub fn node(&self, id: &NodeId) -> Option<&Node> {
373        self.nodes.get(id)
374    }
375
376    /// Returns one mutable node.
377    pub(crate) fn node_mut(&mut self, id: &NodeId) -> Option<&mut Node> {
378        self.nodes.get_mut(id)
379    }
380
381    /// Updates one node through a controlled mutable callback.
382    pub(crate) fn update_node<R>(
383        &mut self,
384        id: &NodeId,
385        f: impl FnOnce(&mut Node) -> R,
386    ) -> Option<R> {
387        self.nodes.get_mut(id).map(f)
388    }
389
390    /// Inserts or replaces a node.
391    pub(crate) fn insert_node(&mut self, id: NodeId, value: Node) -> Option<Node> {
392        self.nodes.insert(id, value)
393    }
394
395    /// Removes a node.
396    pub(crate) fn remove_node(&mut self, id: &NodeId) -> Option<Node> {
397        self.nodes.remove(id)
398    }
399
400    /// Clears all graph nodes.
401    pub(crate) fn clear_nodes(&mut self) {
402        self.nodes.clear();
403    }
404
405    /// Retains graph nodes matching `f`.
406    pub(crate) fn retain_nodes(&mut self, f: impl FnMut(&NodeId, &mut Node) -> bool) {
407        self.nodes.retain(f);
408    }
409
410    /// Returns graph ports.
411    pub fn ports(&self) -> GraphElements<'_, PortId, Port> {
412        GraphElements::new(&self.ports)
413    }
414
415    /// Returns one port.
416    pub fn port(&self, id: &PortId) -> Option<&Port> {
417        self.ports.get(id)
418    }
419
420    /// Returns one mutable port.
421    pub(crate) fn port_mut(&mut self, id: &PortId) -> Option<&mut Port> {
422        self.ports.get_mut(id)
423    }
424
425    /// Updates one port through a controlled mutable callback.
426    pub(crate) fn update_port<R>(
427        &mut self,
428        id: &PortId,
429        f: impl FnOnce(&mut Port) -> R,
430    ) -> Option<R> {
431        self.ports.get_mut(id).map(f)
432    }
433
434    /// Inserts or replaces a port.
435    pub(crate) fn insert_port(&mut self, id: PortId, value: Port) -> Option<Port> {
436        self.ports.insert(id, value)
437    }
438
439    /// Removes a port.
440    pub(crate) fn remove_port(&mut self, id: &PortId) -> Option<Port> {
441        self.ports.remove(id)
442    }
443
444    /// Clears all graph ports.
445    pub(crate) fn clear_ports(&mut self) {
446        self.ports.clear();
447    }
448
449    /// Retains graph ports matching `f`.
450    pub(crate) fn retain_ports(&mut self, f: impl FnMut(&PortId, &mut Port) -> bool) {
451        self.ports.retain(f);
452    }
453
454    /// Returns graph edges.
455    pub fn edges(&self) -> GraphElements<'_, EdgeId, Edge> {
456        GraphElements::new(&self.edges)
457    }
458
459    /// Returns one edge.
460    pub fn edge(&self, id: &EdgeId) -> Option<&Edge> {
461        self.edges.get(id)
462    }
463
464    /// Returns one mutable edge.
465    pub(crate) fn edge_mut(&mut self, id: &EdgeId) -> Option<&mut Edge> {
466        self.edges.get_mut(id)
467    }
468
469    /// Updates one edge through a controlled mutable callback.
470    pub(crate) fn update_edge<R>(
471        &mut self,
472        id: &EdgeId,
473        f: impl FnOnce(&mut Edge) -> R,
474    ) -> Option<R> {
475        self.edges.get_mut(id).map(f)
476    }
477
478    /// Inserts or replaces an edge.
479    pub(crate) fn insert_edge(&mut self, id: EdgeId, value: Edge) -> Option<Edge> {
480        self.edges.insert(id, value)
481    }
482
483    /// Removes an edge.
484    pub(crate) fn remove_edge(&mut self, id: &EdgeId) -> Option<Edge> {
485        self.edges.remove(id)
486    }
487
488    /// Clears all graph edges.
489    pub(crate) fn clear_edges(&mut self) {
490        self.edges.clear();
491    }
492
493    /// Retains graph edges matching `f`.
494    pub(crate) fn retain_edges(&mut self, f: impl FnMut(&EdgeId, &mut Edge) -> bool) {
495        self.edges.retain(f);
496    }
497
498    /// Returns graph groups.
499    pub fn groups(&self) -> GraphElements<'_, GroupId, Group> {
500        GraphElements::new(&self.groups)
501    }
502
503    /// Returns one group.
504    pub fn group(&self, id: &GroupId) -> Option<&Group> {
505        self.groups.get(id)
506    }
507
508    /// Returns one mutable group.
509    pub(crate) fn group_mut(&mut self, id: &GroupId) -> Option<&mut Group> {
510        self.groups.get_mut(id)
511    }
512
513    /// Updates one group through a controlled mutable callback.
514    pub(crate) fn update_group<R>(
515        &mut self,
516        id: &GroupId,
517        f: impl FnOnce(&mut Group) -> R,
518    ) -> Option<R> {
519        self.groups.get_mut(id).map(f)
520    }
521
522    /// Inserts or replaces a group.
523    pub(crate) fn insert_group(&mut self, id: GroupId, value: Group) -> Option<Group> {
524        self.groups.insert(id, value)
525    }
526
527    /// Removes a group.
528    pub(crate) fn remove_group(&mut self, id: &GroupId) -> Option<Group> {
529        self.groups.remove(id)
530    }
531
532    /// Clears all graph groups.
533    pub(crate) fn clear_groups(&mut self) {
534        self.groups.clear();
535    }
536
537    /// Retains graph groups matching `f`.
538    pub(crate) fn retain_groups(&mut self, f: impl FnMut(&GroupId, &mut Group) -> bool) {
539        self.groups.retain(f);
540    }
541
542    /// Returns sticky notes.
543    pub fn sticky_notes(&self) -> GraphElements<'_, StickyNoteId, StickyNote> {
544        GraphElements::new(&self.sticky_notes)
545    }
546
547    /// Returns one sticky note.
548    pub fn sticky_note(&self, id: &StickyNoteId) -> Option<&StickyNote> {
549        self.sticky_notes.get(id)
550    }
551
552    /// Returns one mutable sticky note.
553    pub(crate) fn sticky_note_mut(&mut self, id: &StickyNoteId) -> Option<&mut StickyNote> {
554        self.sticky_notes.get_mut(id)
555    }
556
557    /// Updates one sticky note through a controlled mutable callback.
558    pub(crate) fn update_sticky_note<R>(
559        &mut self,
560        id: &StickyNoteId,
561        f: impl FnOnce(&mut StickyNote) -> R,
562    ) -> Option<R> {
563        self.sticky_notes.get_mut(id).map(f)
564    }
565
566    /// Inserts or replaces a sticky note.
567    pub(crate) fn insert_sticky_note(
568        &mut self,
569        id: StickyNoteId,
570        value: StickyNote,
571    ) -> Option<StickyNote> {
572        self.sticky_notes.insert(id, value)
573    }
574
575    /// Removes a sticky note.
576    pub(crate) fn remove_sticky_note(&mut self, id: &StickyNoteId) -> Option<StickyNote> {
577        self.sticky_notes.remove(id)
578    }
579
580    /// Clears all sticky notes.
581    pub(crate) fn clear_sticky_notes(&mut self) {
582        self.sticky_notes.clear();
583    }
584
585    /// Retains sticky notes matching `f`.
586    pub(crate) fn retain_sticky_notes(
587        &mut self,
588        f: impl FnMut(&StickyNoteId, &mut StickyNote) -> bool,
589    ) {
590        self.sticky_notes.retain(f);
591    }
592
593    /// Returns bindings.
594    pub fn bindings(&self) -> GraphElements<'_, BindingId, Binding> {
595        GraphElements::new(&self.bindings)
596    }
597
598    /// Returns one binding.
599    pub fn binding(&self, id: &BindingId) -> Option<&Binding> {
600        self.bindings.get(id)
601    }
602
603    /// Returns one mutable binding.
604    pub(crate) fn binding_mut(&mut self, id: &BindingId) -> Option<&mut Binding> {
605        self.bindings.get_mut(id)
606    }
607
608    /// Updates one binding through a controlled mutable callback.
609    pub(crate) fn update_binding<R>(
610        &mut self,
611        id: &BindingId,
612        f: impl FnOnce(&mut Binding) -> R,
613    ) -> Option<R> {
614        self.bindings.get_mut(id).map(f)
615    }
616
617    /// Inserts or replaces a binding.
618    pub(crate) fn insert_binding(&mut self, id: BindingId, value: Binding) -> Option<Binding> {
619        self.bindings.insert(id, value)
620    }
621
622    /// Removes a binding.
623    pub(crate) fn remove_binding(&mut self, id: &BindingId) -> Option<Binding> {
624        self.bindings.remove(id)
625    }
626
627    /// Clears all bindings.
628    pub(crate) fn clear_bindings(&mut self) {
629        self.bindings.clear();
630    }
631
632    /// Retains bindings matching `f`.
633    pub(crate) fn retain_bindings(&mut self, f: impl FnMut(&BindingId, &mut Binding) -> bool) {
634        self.bindings.retain(f);
635    }
636}