use serde::{Deserialize, Serialize};
use crate::topology::node::NodeView;
#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
pub struct NodeFilter {
#[serde(default)]
pub node_types: Vec<String>,
pub label_contains: Option<String>,
#[serde(default)]
pub leaves_only: bool,
}
impl NodeFilter {
pub fn all() -> Self {
Self::default()
}
pub fn by_type(node_type: impl Into<String>) -> Self {
Self {
node_types: vec![node_type.into()],
..Self::default()
}
}
pub fn by_types(types: Vec<String>) -> Self {
Self {
node_types: types,
..Self::default()
}
}
pub fn is_empty(&self) -> bool {
self.node_types.is_empty() && self.label_contains.is_none() && !self.leaves_only
}
pub fn apply(&self, nodes: &[NodeView]) -> Vec<NodeView> {
if self.is_empty() {
return nodes.to_vec();
}
nodes
.iter()
.filter_map(|node| self.filter_node(node))
.collect()
}
fn filter_node(&self, node: &NodeView) -> Option<NodeView> {
if node.is_leaf() {
if self.matches_leaf(node) {
return Some(node.clone());
}
return None;
}
let filtered_children: Vec<NodeView> = node
.children
.iter()
.filter_map(|c| self.filter_node(c))
.collect();
if filtered_children.is_empty() {
return None;
}
let mut result = node.clone();
result.children = filtered_children;
Some(result)
}
fn matches_leaf(&self, node: &NodeView) -> bool {
if !self.node_types.is_empty() && !self.node_types.contains(&node.node_type) {
return false;
}
if let Some(ref label_substr) = self.label_contains
&& !node
.label
.to_lowercase()
.contains(&label_substr.to_lowercase())
{
return false;
}
true
}
}