use crate::{
core::entities::{edges::edge_ref::EdgeRef, VID},
db::api::{
properties::internal::InternalPropertiesOps,
state::ops::{self, ArrowNodeOp, IntoArrowNodeOp, NodeOp},
view::{node_edges, TimeOps},
},
prelude::{EdgeViewOps, GraphViewOps, LayerOps},
};
use itertools::Itertools;
use raphtory_api::core::Direction;
use raphtory_storage::graph::graph::GraphStorage;
use serde::{Deserialize, Serialize};
pub trait BaseNodeViewOps<'graph>: Clone + TimeOps<'graph> + LayerOps<'graph> {
type Graph: GraphViewOps<'graph>;
type ValueType<Op>: 'graph
where
Op: ArrowNodeOp + 'graph,
Op::Output: 'graph;
type PropType: InternalPropertiesOps + Clone + 'graph;
type PathType: NodeViewOps<'graph, Graph = Self::Graph> + 'graph;
type Edges: EdgeViewOps<'graph, Graph = Self::Graph> + 'graph;
fn graph(&self) -> &Self::Graph;
fn map<F: ArrowNodeOp + Clone + 'graph>(&self, op: F) -> Self::ValueType<F>;
fn map_edges<
I: Iterator<Item = EdgeRef> + Send + Sync + 'graph,
F: Fn(&GraphStorage, &Self::Graph, VID) -> I + Send + Sync + Clone + 'graph,
>(
&self,
op: F,
) -> Self::Edges;
fn hop<
I: Iterator<Item = VID> + Send + Sync + 'graph,
F: for<'a> Fn(&GraphStorage, &'a Self::Graph, VID) -> I + Send + Sync + Clone + 'graph,
>(
&self,
op: F,
) -> Self::PathType;
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct IsActiveRow {
is_active: bool,
}
impl From<bool> for IsActiveRow {
fn from(is_active: bool) -> Self {
IsActiveRow { is_active }
}
}
pub trait NodeViewOps<'graph>: Clone + TimeOps<'graph> + LayerOps<'graph> {
type Graph: GraphViewOps<'graph>;
type ValueType<T: ArrowNodeOp>: 'graph
where
T: 'graph,
T::Output: 'graph;
type PathType: NodeViewOps<'graph, Graph = Self::Graph> + 'graph;
type Edges: EdgeViewOps<'graph, Graph = Self::Graph> + 'graph;
fn id(&self) -> Self::ValueType<ops::Id>;
fn name(&self) -> Self::ValueType<ops::Name>;
fn node_type(&self) -> Self::ValueType<ops::Type>;
fn node_type_id(&self) -> Self::ValueType<ops::TypeId>;
fn earliest_time(&self) -> Self::ValueType<ops::EarliestTime<Self::Graph>>;
fn latest_time(&self) -> Self::ValueType<ops::LatestTime<Self::Graph>>;
fn history(&self) -> Self::ValueType<ops::HistoryOp<'graph, Self::Graph>>;
fn edge_history_count(&self) -> Self::ValueType<ops::EdgeHistoryCount<Self::Graph>>;
fn is_active(
&self,
) -> Self::ValueType<
ops::ArrowMap<ops::Map<ops::HistoryOp<'graph, Self::Graph>, bool>, IsActiveRow>,
>;
fn properties(&self) -> Self::ValueType<ops::GetProperties<'graph, Self::Graph>>;
fn metadata(&self) -> Self::ValueType<ops::GetMetadata<'graph, Self::Graph>>;
fn degree(&self) -> Self::ValueType<ops::Degree<Self::Graph>>;
fn in_degree(&self) -> Self::ValueType<ops::Degree<Self::Graph>>;
fn out_degree(&self) -> Self::ValueType<ops::Degree<Self::Graph>>;
fn edges(&self) -> Self::Edges;
fn in_edges(&self) -> Self::Edges;
fn out_edges(&self) -> Self::Edges;
fn neighbours(&self) -> Self::PathType;
fn in_neighbours(&self) -> Self::PathType;
fn out_neighbours(&self) -> Self::PathType;
}
impl<'graph, V: BaseNodeViewOps<'graph> + 'graph> NodeViewOps<'graph> for V {
type Graph = V::Graph;
type ValueType<T: ArrowNodeOp + 'graph>
= V::ValueType<T>
where
T::Output: 'graph;
type PathType = V::PathType;
type Edges = V::Edges;
#[inline]
fn id(&self) -> Self::ValueType<ops::Id> {
self.map(ops::Id)
}
#[inline]
fn name(&self) -> Self::ValueType<ops::Name> {
self.map(ops::Name)
}
#[inline]
fn node_type(&self) -> Self::ValueType<ops::Type> {
self.map(ops::Type)
}
#[inline]
fn node_type_id(&self) -> Self::ValueType<ops::TypeId> {
self.map(ops::TypeId)
}
#[inline]
fn earliest_time(&self) -> Self::ValueType<ops::EarliestTime<Self::Graph>> {
let op = ops::EarliestTime {
view: self.graph().clone(),
};
self.map(op)
}
#[inline]
fn latest_time(&self) -> Self::ValueType<ops::LatestTime<Self::Graph>> {
let op = ops::LatestTime {
view: self.graph().clone(),
};
self.map(op)
}
fn history(&self) -> Self::ValueType<ops::HistoryOp<'graph, Self::Graph>> {
let op = ops::HistoryOp::new(self.graph().clone());
self.map(op)
}
#[inline]
fn edge_history_count(&self) -> Self::ValueType<ops::EdgeHistoryCount<Self::Graph>> {
let op = ops::EdgeHistoryCount {
view: self.graph().clone(),
};
self.map(op)
}
fn is_active(
&self,
) -> Self::ValueType<
ops::ArrowMap<ops::Map<ops::HistoryOp<'graph, Self::Graph>, bool>, IsActiveRow>,
> {
let op = ops::HistoryOp::new(self.graph().clone()).map(|h| !h.is_empty());
self.map(op.into_arrow_node_op())
}
#[inline]
fn properties(&self) -> Self::ValueType<ops::GetProperties<'graph, Self::Graph>> {
let op = ops::GetProperties::new(self.graph().clone());
self.map(op)
}
#[inline]
fn metadata(&self) -> Self::ValueType<ops::GetMetadata<'graph, Self::Graph>> {
let op = ops::GetMetadata::new(self.graph().clone());
self.map(op)
}
#[inline]
fn degree(&self) -> Self::ValueType<ops::Degree<Self::Graph>> {
let op = ops::Degree {
view: self.graph().clone(),
dir: Direction::BOTH,
};
self.map(op)
}
#[inline]
fn in_degree(&self) -> Self::ValueType<ops::Degree<Self::Graph>> {
let op = ops::Degree {
dir: Direction::IN,
view: self.graph().clone(),
};
self.map(op)
}
#[inline]
fn out_degree(&self) -> Self::ValueType<ops::Degree<Self::Graph>> {
let op = ops::Degree {
view: self.graph().clone(),
dir: Direction::OUT,
};
self.map(op)
}
#[inline]
fn edges(&self) -> Self::Edges {
self.map_edges(|cg, g, v| {
let cg = cg.clone();
let g = g.clone();
node_edges(cg, g, v, Direction::BOTH)
})
}
#[inline]
fn in_edges(&self) -> Self::Edges {
self.map_edges(|cg, g, v| {
let cg = cg.clone();
let g = g.clone();
node_edges(cg, g, v, Direction::IN)
})
}
#[inline]
fn out_edges(&self) -> Self::Edges {
self.map_edges(|cg, g, v| {
let cg = cg.clone();
let g = g.clone();
node_edges(cg, g, v, Direction::OUT)
})
}
#[inline]
fn neighbours(&self) -> Self::PathType {
self.hop(|cg, g, v| {
let cg = cg.clone();
let g = g.clone();
node_edges(cg, g, v, Direction::BOTH)
.map(|e| e.remote())
.dedup()
})
}
#[inline]
fn in_neighbours(&self) -> Self::PathType {
self.hop(|cg, g, v| {
let cg = cg.clone();
let g = g.clone();
node_edges(cg, g, v, Direction::IN)
.map(|e| e.remote())
.dedup()
})
}
#[inline]
fn out_neighbours(&self) -> Self::PathType {
self.hop(|cg, g, v| {
let cg = cg.clone();
let g = g.clone();
node_edges(cg, g, v, Direction::OUT)
.map(|e| e.remote())
.dedup()
})
}
}