reactive_graph_behaviour_model_impl/behaviour/relation/
observer.rs

1use dashmap::DashMap;
2use dashmap::DashSet;
3use log::trace;
4use serde_json::Value;
5use uuid::Uuid;
6
7use crate::PropertyObserverContainer;
8use reactive_graph_graph::PropertyInstanceSetter;
9use reactive_graph_reactive_model_api::ReactivePropertyContainer;
10use reactive_graph_reactive_model_impl::ReactiveRelation;
11
12/// Container which manages the observers of a reactive relation instance.
13pub struct RelationPropertyObserverContainerImpl {
14    pub reactive_instance: ReactiveRelation,
15    pub handles: DashMap<String, DashSet<u128>>,
16}
17
18impl RelationPropertyObserverContainerImpl {
19    /// Creates a property observer container for the given reactive relation instance.
20    pub fn new(reactive_instance: ReactiveRelation) -> Self {
21        RelationPropertyObserverContainerImpl {
22            reactive_instance,
23            handles: DashMap::new(),
24        }
25    }
26}
27
28impl PropertyObserverContainer for RelationPropertyObserverContainerImpl {
29    fn observe_with_handle<F>(&self, name: &str, subscriber: F) -> u128
30    where
31        F: FnMut(&Value) + 'static + Send,
32    {
33        let handle_id = Uuid::new_v4().as_u128();
34        match self.handles.get(name) {
35            None => {
36                let property_handles = DashSet::new();
37                property_handles.insert(handle_id);
38                self.handles.insert(name.to_string(), property_handles);
39            }
40            Some(property_handles) => {
41                property_handles.insert(handle_id);
42            }
43        }
44        trace!("Adding observer {} {} {}", self.reactive_instance, name, handle_id);
45        self.reactive_instance.observe_with_handle(name, subscriber, handle_id);
46        handle_id
47    }
48
49    fn propagate(&self, name: &str, target_property_name: &str) {
50        let reactive_instance = self.reactive_instance.clone();
51        let target_property_name = target_property_name.to_string();
52        self.observe_with_handle(name, move |value| {
53            reactive_instance.set(&target_property_name, value.clone());
54        });
55    }
56
57    fn remove_observer(&self, name: &str, handle_id: u128) {
58        self.reactive_instance.remove_observer(name, handle_id);
59        if let Some(property_handles) = self.handles.get(name) {
60            trace!("Removing observer {} {} {}", self.reactive_instance, property_handles.key(), &handle_id);
61            property_handles.remove(&handle_id.clone());
62        }
63    }
64
65    fn remove_observers(&self, name: &str) {
66        if let Some(property_handles) = self.handles.get(name) {
67            for handle_id in property_handles.iter() {
68                trace!("Removing observer {} {} {}", self.reactive_instance, property_handles.key(), handle_id.key());
69                self.reactive_instance.remove_observer(name, *handle_id.key());
70            }
71        }
72        self.handles.remove(name);
73    }
74
75    fn remove_all_observers(&self) {
76        for property_handles in self.handles.iter() {
77            for handle_id in property_handles.iter() {
78                trace!("Removing observer {} {} {}", self.reactive_instance, property_handles.key(), handle_id.key());
79                self.reactive_instance.remove_observer(property_handles.key(), *handle_id.key());
80            }
81        }
82        self.handles.clear();
83    }
84}