gruphst/graphs/
mod.rs

1//! Graphs modules
2
3use log::{error, warn};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6
7use crate::{
8    edge::Edge, errors::GruPHstError, graphs_stats::GraphsStats, util::graphs_memory_watcher,
9    vertex::Vertex,
10};
11
12mod persistence;
13mod queries;
14mod stats;
15
16/// A colection of Graph
17#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct Graphs {
19    /// The container of Edges
20    vault: HashMap<String, Vec<Edge>>,
21    /// Name for the current vault
22    label: String,
23    /// Some attributes to handle metada for Graphs
24    stats: GraphsStats,
25}
26
27impl Graphs {
28    /// Initializes a new Graphs element
29    /// # Examples
30    /// ```rust
31    /// use gruphst::graphs::Graphs;
32    ///  
33    /// Graphs::init("my graph");
34    /// ```
35    pub fn init(label: &str) -> Self {
36        let mut vault: HashMap<String, Vec<Edge>> = HashMap::new();
37        vault.insert(String::from(label), vec![]);
38        Graphs {
39            label: String::from(label),
40            vault,
41            stats: GraphsStats::init(),
42        }
43    }
44
45    /// Initializes a new Graphs element adding a Edge to new vault
46    /// # Examples
47    /// ```rust
48    /// use gruphst::{edge::Edge, vertex::Vertex, graphs::Graphs};
49    ///  
50    /// let edge = Edge::create(
51    ///     &Vertex::new("Sauron"),
52    ///     "created",
53    ///     &Vertex::new("One Ring"));
54    /// Graphs::init_with("my graph", &edge);
55    /// ```
56    pub fn init_with(label: &str, vertex: &Edge) -> Self {
57        let mut graphs = Graphs::init(label);
58        graphs.add_edge(vertex, None);
59        graphs
60    }
61
62    /// Creates a new entry on Graphs valut
63    /// # Examples
64    /// ```rust
65    /// use gruphst::graphs::Graphs;
66    ///  
67    /// let mut graphs = Graphs::init("my graphs");
68    /// graphs.insert("my other graphs");
69    /// ```
70    pub fn insert(&mut self, name: &str) {
71        self.vault.insert(String::from(name), vec![]);
72        self.label = String::from(name);
73        graphs_memory_watcher(self);
74    }
75
76    /// Creates a new entry on Graphs valut with a Graph
77    pub fn insert_with(&mut self, name: &str, edge: &Edge) {
78        self.vault.insert(String::from(name), vec![]);
79        self.label = String::from(name);
80        self.add_edge(edge, Some(name));
81        graphs_memory_watcher(self);
82    }
83
84    /// Returns the label or name for the graphs
85    pub fn get_label(&self) -> String {
86        self.label.clone()
87    }
88
89    /// Sets the label or name for the graphs
90    pub fn set_label(&mut self, label: &str) {
91        self.label = label.to_string()
92    }
93
94    /// Returns the stats for a grpahs
95    /// the stats are generated
96    pub fn get_stats(&mut self) -> GraphsStats {
97        self.stats = GraphsStats::generate_stats(self);
98        self.stats.clone()
99    }
100
101    /// Returns the GraphsStats object
102    pub fn get_graphs_stats(&self) -> GraphsStats {
103        self.stats.clone()
104    }
105
106    pub fn get_vaults(&self) -> Result<HashMap<String, Vec<Edge>>, GruPHstError> {
107        let vaults = self.vault.clone();
108        if vaults.values().len() == 1 {
109            for val in vaults.values() {
110                if val.is_empty() {
111                    return Err(GruPHstError::NoVaultOnGraphs);
112                }
113            }
114            Ok(vaults)
115        } else {
116            Ok(vaults)
117        }
118    }
119
120    /// Adds a Edge element to the Graphs' vault
121    /// for the provided graphs vault name
122    /// if does not exists it creates a new entry
123    /// at vault.
124    /// If None name is provided, the current one
125    /// is use for the addition.
126    pub fn add_edge(&mut self, edge: &Edge, vault_name: Option<&str>) {
127        let current_vault = self.select_vault_label(vault_name);
128        if let Some(e) = self.vault.get_mut(&current_vault) {
129            e.push(edge.clone());
130        } else {
131            self.insert(&current_vault);
132            let v = self.vault.get_mut(&current_vault).unwrap();
133            v.push(edge.clone());
134        }
135        graphs_memory_watcher(self);
136    }
137
138    /// Adds a collection of Edges to the Graphs' vault
139    /// for the provided graphs vault name
140    /// if does not exists it creates a new entry
141    /// at vault.
142    /// If None name is provided, the current one
143    /// is use for the addition.
144    pub fn add_edges(&mut self, edges: &mut Vec<Edge>, vault_name: Option<&str>) {
145        let current_vault = self.select_vault_label(vault_name);
146        if let Some(e) = self.vault.get_mut(&current_vault) {
147            e.append(edges);
148        } else {
149            self.insert(&current_vault);
150            let v = self.vault.get_mut(&current_vault).unwrap();
151            v.append(edges);
152        }
153        graphs_memory_watcher(self);
154    }
155
156    /// Retrieves the collection of edges
157    /// the default one or by name
158    pub fn get_edges(&self, vault_name: Option<&str>) -> Result<Vec<Edge>, GruPHstError> {
159        Ok(self.select_vault(vault_name)?)
160    }
161
162    /// Returns a collection with the unique vertices on a vault
163    pub fn get_uniq_vertices(&self, vault_name: Option<&str>) -> Result<Vec<Vertex>, GruPHstError> {
164        let edges = self.select_vault(vault_name)?;
165        let mut vertices_map: HashMap<String, Vertex> = HashMap::new();
166        for edge in edges {
167            vertices_map.insert(edge.get_from_vertex().get_id(), edge.get_from_vertex());
168            vertices_map.insert(edge.get_to_vertex().get_id(), edge.get_to_vertex());
169        }
170        let uniq_vertices: Vec<Vertex> = vertices_map.into_values().collect();
171        Ok(uniq_vertices)
172    }
173
174    /// Returns a collection with the unique vertices from all vaults
175    pub fn get_uniq_vertices_on_graphs(&self) -> Result<Vec<Vertex>, GruPHstError> {
176        let vaults = self.get_vaults()?;
177        let mut vertices_map: HashMap<String, Vertex> = HashMap::new();
178        for (_, edges) in vaults {
179            for edge in edges {
180                vertices_map.insert(edge.get_from_vertex().get_id(), edge.get_from_vertex());
181                vertices_map.insert(edge.get_to_vertex().get_id(), edge.get_to_vertex());
182            }
183        }
184        let uniq_vertices: Vec<Vertex> = vertices_map.into_values().collect();
185        Ok(uniq_vertices)
186    }
187
188    /// Updates the name of the Graphs
189    pub fn update_label(&mut self, label: &str) {
190        self.label = label.to_string();
191    }
192
193    /// Deletes the Edge that matches with the provided id
194    pub fn delete_edge_by_id(
195        &mut self,
196        id: String,
197        vault_name: Option<&str>,
198    ) -> Result<(), GruPHstError> {
199        let edges = self.select_vault_mut(vault_name)?;
200        if let Some(index) = edges.iter().position(|edge| edge.get_id() == id) {
201            edges.remove(index);
202            graphs_memory_watcher(self);
203            Ok(())
204        } else {
205            error!("Edge [{}] to delete not found", id);
206            Err(GruPHstError::EdgeNotFound)
207        }
208    }
209
210    /// Updates the Edge on vault with the provided one
211    pub fn update_graph(
212        &mut self,
213        edge_to_update: &Edge,
214        vault_name: Option<&str>,
215    ) -> Result<(), GruPHstError> {
216        let edges: &mut Vec<Edge> = self.select_vault_mut(vault_name)?;
217        let index = edges
218            .iter()
219            .position(|vertex| vertex.get_id() == edge_to_update.get_id());
220        if index.is_some() {
221            let i = index.unwrap();
222            edges.remove(i);
223            edges.push(edge_to_update.clone());
224            graphs_memory_watcher(self);
225            Ok(())
226        } else {
227            #[rustfmt::skip]
228            error!("Edge to update with id: [{}] not found", edge_to_update.get_id());
229            Err(GruPHstError::EdgeNotFound)
230        }
231    }
232
233    /// Retrieves the current vault or returns the current one
234    fn select_vault_label(&self, vault_label: Option<&str>) -> String {
235        let mut current_vault = self.label.clone();
236        if let Some(vlt) = vault_label {
237            current_vault = vlt.to_string();
238        }
239        current_vault.to_string()
240    }
241
242    fn select_vault_not_exists_error(vault: String) -> GruPHstError {
243        warn!("Vault {} does not exists", vault);
244        GruPHstError::VaultNotExists(vault)
245    }
246
247    fn select_vault_mut(
248        &mut self,
249        vault_label: Option<&str>,
250    ) -> Result<&mut Vec<Edge>, GruPHstError> {
251        let vault = self.select_vault_label(vault_label);
252        if let Some(edges) = self.vault.get_mut(&vault) {
253            match edges.is_empty() {
254                false => Ok(edges),
255                true => Err(GruPHstError::VaultEmpty),
256            }
257        } else {
258            Err(Graphs::select_vault_not_exists_error(vault))
259        }
260    }
261
262    fn select_vault(&self, vault_label: Option<&str>) -> Result<Vec<Edge>, GruPHstError> {
263        let vault = self.select_vault_label(vault_label);
264        if let Some(edges) = self.vault.get(&vault) {
265            match edges.is_empty() {
266                false => Ok(edges.clone()),
267                true => Err(GruPHstError::VaultEmpty),
268            }
269        } else {
270            Err(Graphs::select_vault_not_exists_error(vault))
271        }
272    }
273
274    /// Removes a graph from the vault
275    ///
276    /// #Examples
277    /// ```rust
278    /// use gruphst::graphs::Graphs;
279    ///
280    /// let mut graphs = Graphs::init("graph-one");
281    /// assert_eq!(graphs.len_graphs(), 1);
282    /// graphs.insert("graph-two");
283    /// assert_eq!(graphs.len_graphs(), 2);
284    /// graphs.delete_vault("graph-two").unwrap();
285    /// ```
286    pub fn delete_vault(&mut self, graph_name: &str) -> Result<(), GruPHstError> {
287        match self.vault.remove(graph_name) {
288            Some(_) => Ok(()),
289            None => Err(GruPHstError::VaultNotExists(graph_name.to_string())),
290        }
291    }
292}