use crate::{
db::{
api::view::internal::{InternalFilter, InternalLayerOps},
graph::views::layer_graph::LayeredGraph,
},
errors::GraphError,
prelude::GraphViewOps,
};
use raphtory_api::core::entities::{Layer, LayerIds, SingleLayer};
use raphtory_storage::core_ops::CoreGraphOps;
pub trait LayerOps<'graph> {
type LayeredViewType;
fn default_layer(&self) -> Self::LayeredViewType {
self.valid_layers(Layer::Default)
}
fn layers<L: Into<Layer>>(&self, names: L) -> Result<Self::LayeredViewType, GraphError>;
fn exclude_layers<L: Into<Layer>>(
&self,
layers: L,
) -> Result<Self::LayeredViewType, GraphError>;
fn exclude_valid_layers<L: Into<Layer>>(&self, layers: L) -> Self::LayeredViewType;
fn has_layer<L: SingleLayer>(&self, name: L) -> bool;
fn valid_layers<L: Into<Layer>>(&self, names: L) -> Self::LayeredViewType;
fn num_layers(&self) -> usize;
}
impl<'graph, V: InternalFilter<'graph> + 'graph> LayerOps<'graph> for V {
type LayeredViewType = V::Filtered<LayeredGraph<V::Graph>>;
fn default_layer(&self) -> Self::LayeredViewType {
let layers = match self.base_graph().get_default_layer_id() {
None => LayerIds::None,
Some(layer) => {
if self.base_graph().layer_ids().contains(&layer) {
LayerIds::One(layer)
} else {
LayerIds::None
}
}
};
self.apply_filter(LayeredGraph::new(self.base_graph().clone(), layers))
}
fn layers<L: Into<Layer>>(&self, layers: L) -> Result<Self::LayeredViewType, GraphError> {
let layers = layers.into();
let ids = self.base_graph().layer_ids_from_names(layers)?;
Ok(self.apply_filter(LayeredGraph::new(self.base_graph().clone(), ids)))
}
fn exclude_layers<L: Into<Layer>>(
&self,
layers: L,
) -> Result<Self::LayeredViewType, GraphError> {
let all_layer_ids = self.base_graph().layer_ids();
let excluded_ids = self.base_graph().layer_ids_from_names(layers.into())?;
let included_ids = diff(all_layer_ids, self.base_graph().clone(), &excluded_ids);
Ok(self.apply_filter(LayeredGraph::new(self.base_graph().clone(), included_ids)))
}
fn exclude_valid_layers<L: Into<Layer>>(&self, layers: L) -> Self::LayeredViewType {
let all_layer_ids = self.base_graph().layer_ids();
let excluded_ids = self.base_graph().valid_layer_ids_from_names(layers.into());
let included_ids = diff(all_layer_ids, self.base_graph().clone(), &excluded_ids);
self.apply_filter(LayeredGraph::new(self.base_graph().clone(), included_ids))
}
fn has_layer<L: SingleLayer>(&self, name: L) -> bool {
!self
.base_graph()
.valid_layer_ids_from_names(name.into())
.is_none()
}
fn valid_layers<L: Into<Layer>>(&self, names: L) -> Self::LayeredViewType {
let layers = names.into();
let ids = self.base_graph().valid_layer_ids_from_names(layers);
self.apply_filter(LayeredGraph::new(self.base_graph().clone(), ids))
}
fn num_layers(&self) -> usize {
self.base_graph().unique_layers().count()
}
}
pub fn diff<'a>(left: &LayerIds, graph: impl GraphViewOps<'a>, other: &LayerIds) -> LayerIds {
match (left, other) {
(LayerIds::None, _) => LayerIds::None,
(this, LayerIds::None) => this.clone(),
(_, LayerIds::All) => LayerIds::None,
(LayerIds::One(id), other) => {
if other.contains(id) {
LayerIds::None
} else {
LayerIds::One(*id)
}
}
(LayerIds::Multiple(ids), other) => {
let ids: Vec<usize> = ids.iter().filter(|id| !other.contains(id)).collect();
match ids.len() {
0 => LayerIds::None,
1 => LayerIds::One(ids[0]),
_ => LayerIds::Multiple(ids.into()),
}
}
(LayerIds::All, other) => {
let all_layer_ids: Vec<usize> = graph
.unique_layers()
.map(|name| graph.get_layer_id(name.as_ref()).unwrap())
.filter(|id| !other.contains(id))
.collect();
match all_layer_ids.len() {
0 => LayerIds::None,
1 => LayerIds::One(all_layer_ids[0]),
_ => LayerIds::Multiple(all_layer_ids.into()),
}
}
}
}