use std::{collections::{HashMap, HashSet}, ops::{Index, IndexMut}};
use anyhow::Result;
use nanoid::nanoid;
use serde::{Deserialize, Serialize};
use crate::{lang::SError, SField};
use super::{IntoDataRef, IntoNodeRef, SData, SDataRef, SDataStore, SNode, SNodeRef, SNodeStore, SRef, Store, DATA_DIRTY_NODES};
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum SVersion {
#[default]
V1 = 1,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SGraph {
pub id: String,
pub name: String,
pub version: SVersion,
pub roots: Vec<SNodeRef>,
pub nodes: Box<SNodeStore>,
pub data: Box<SDataStore>,
}
impl Default for SGraph {
fn default() -> Self {
let id = nanoid!();
Self {
id: id.clone(),
name: id,
version: Default::default(),
roots: Default::default(),
nodes: Default::default(),
data: Default::default(),
}
}
}
impl Index<&str> for SGraph {
type Output = SNode;
fn index(&self, index: &str) -> &Self::Output {
self.node_from(index, None).expect("Node not found for path")
}
}
impl IndexMut<&str> for SGraph {
fn index_mut(&mut self, index: &str) -> &mut Self::Output {
self.node_from_mut(index, None).expect("Node not found for path")
}
}
impl SGraph {
pub fn new(name: &str) -> Self {
Self {
id: nanoid!(),
name: name.to_owned(),
..Default::default()
}
}
pub fn new_id(name: &str, id: &str) -> Self {
Self {
id: id.to_owned(),
name: name.to_owned(),
..Default::default()
}
}
pub fn node(&self, nref: impl SRef) -> Option<&SNode> {
self.nodes.get(&nref.get())
}
pub fn node_mut(&mut self, nref: impl SRef) -> Option<&mut SNode> {
self.nodes.get_mut(&nref.get())
}
pub fn node_ref(&self, path: &str, start: Option<&SNodeRef>) -> Option<SNodeRef> {
SNodeRef::node_from(self, path, start)
}
pub fn node_refs(&self, path: &str) -> Vec<SNodeRef> {
SNodeRef::nodes_from(self, path)
}
pub fn node_from(&self, path: &str, start: Option<&SNodeRef>) -> Option<&SNode> {
if let Some(node_ref) = self.node_ref(path, start) {
return node_ref.node(self);
}
None
}
pub fn node_from_mut(&mut self, path: &str, start: Option<&SNodeRef>) -> Option<&mut SNode> {
if let Some(node_ref) = self.node_ref(path, start) {
return node_ref.node_mut(self);
}
None
}
pub fn root_count(&self) -> usize {
self.roots.len()
}
pub fn main_root(&self) -> Option<SNodeRef> {
if self.roots.len() > 0 {
Some(self.roots.first().unwrap().clone())
} else {
None
}
}
pub fn root_by_name(&self, name: &str) -> Option<SNodeRef> {
for root in &self.roots {
if let Some(node) = root.node(self) {
if node.name == name { return Some(root.clone()); }
}
}
None
}
pub fn is_root_id(&self, id: &str) -> bool {
for root in &self.roots {
if root.id == id { return true; }
}
false
}
pub fn push_root(&mut self, id: &str) -> bool {
if !self.is_root_id(id) {
self.roots.push(SNodeRef::from(id));
return true;
}
false
}
pub fn remove_root(&mut self, id: &str) -> bool {
let mut count = 0;
self.roots.retain(|x| -> bool {
let keep = x.id != id;
if !keep { count += 1; }
keep
});
count > 0
}
pub fn data_ref(&self, id: &str) -> Option<SDataRef> {
if self.data.contains(id) {
return Some(SDataRef::from(id));
}
None
}
pub fn data_from_ref(&self, to_ref: impl IntoDataRef) -> Option<&SData> {
to_ref.data_ref().data(self)
}
pub fn data_from_id(&self, id: &str) -> Option<&SData> {
self.data.get(id)
}
pub fn data_from_id_mut(&mut self, id: &str) -> Option<&mut SData> {
self.data.get_mut(id)
}
pub fn insert_root(&mut self, name: &str) -> SNodeRef {
let mut node = SNode::new(name);
let node_ref = node.node_ref();
node.invalidate_all();
self.nodes.set(&node.id.clone(), node);
self.push_root(&node_ref.id);
node_ref
}
pub fn insert_node(&mut self, name: &str, parent: Option<&SNodeRef>) -> SNodeRef {
let node = SNode::new(name);
self.insert_node_raw(node, parent)
}
pub fn insert_node_with_id(&mut self, name: &str, id: &str, parent: Option<&SNodeRef>) -> SNodeRef {
let node = SNode::new_id(name, id);
self.insert_node_raw(node, parent)
}
pub fn insert_node_raw(&mut self, mut node: SNode, parent: Option<&SNodeRef>) -> SNodeRef {
if let Some(parent) = parent {
if parent.exists(self) {
node.parent = Some(parent.clone());
} else {
node.parent = None;
}
} else {
node.parent = None;
}
let res = node.node_ref();
node.invalidate_all();
self.nodes.set(&node.id.clone(), node);
if let Some(parent) = parent {
if let Some(parent_node) = parent.node_mut(self) {
parent_node.put_child(&res);
}
} else {
self.push_root(&res.id);
}
res
}
pub fn ensure_nodes(&mut self, path: &str, sep: char, fields: bool, start: Option<SNodeRef>) -> SNodeRef {
let mut current: Option<SNodeRef> = start;
for segment in path.split(sep).collect::<Vec<&str>>() {
if let Some(node) = self.node_ref(segment, current.as_ref()) {
current = Some(node);
} else {
if fields && current.is_some() {
current = Some(crate::SField::new_object(self, segment, ¤t.unwrap()));
} else {
current = Some(self.insert_node(segment, current.as_ref()));
}
}
}
if let Some(nref) = current {
return nref;
}
Default::default()
}
pub fn rename_node(&mut self, node: impl IntoNodeRef, new_name: &str) -> bool {
let node_ref = node.node_ref();
if let Some(node) = node_ref.node_mut(self) {
node.name = new_name.to_owned();
return true;
}
false
}
pub fn remove_node(&mut self, node: impl IntoNodeRef) -> bool {
let node_ref = node.node_ref();
if !node_ref.exists(self) { return false; }
let mut data_to_remove: Vec<SDataRef> = vec![];
let mut nodes_to_remove: Vec<SNodeRef> = vec![];
let mut parent: Option<SNodeRef> = None;
if let Some(node) = node_ref.node(self) {
data_to_remove = node.data.iter().cloned().collect();
nodes_to_remove = node.children.iter().cloned().collect();
parent = node.parent.clone();
}
for dref in &data_to_remove {
self.remove_data(dref, Some(&node_ref));
}
self.nodes.remove(&node_ref.id);
for nref in &nodes_to_remove {
self.remove_node(nref);
}
if parent.is_some() {
if let Some(parent) = parent.unwrap().node_mut(self) {
parent.remove_child(&node_ref);
}
}
self.remove_root(&node_ref.id);
true
}
pub fn all_children(&self, node: impl IntoNodeRef) -> Vec<SNodeRef> {
let node_ref = node.node_ref();
let mut map = HashMap::new();
if let Some(node) = node_ref.node(self) {
for child_ref in &node.children {
map.insert(child_ref.id.clone(), self.all_children(child_ref));
}
}
let mut res = Vec::new();
for (id, mut children) in map {
res.push(id.into());
res.append(&mut children);
}
res
}
pub fn move_node_up(&mut self, node: impl IntoNodeRef, allow_root: bool) -> Vec<SNodeRef> {
let node_ref = node.node_ref();
let mut push_child = Vec::new();
let mut remove_child = Vec::new();
if let Some(node) = node_ref.node(self) {
if let Some(parent) = &node.parent {
if let Some(parent) = parent.node(self) {
if let Some(grandparent) = &parent.parent {
if let Some(grandparent) = grandparent.node(self) {
push_child.push(grandparent.node_ref());
remove_child.push(parent.node_ref());
}
} else if allow_root {
remove_child.push(parent.node_ref());
}
}
}
}
let mut res = vec![];
if remove_child.len() > 0 {
if let Some(parent) = remove_child[0].node_mut(self) {
parent.remove_child(&node_ref);
}
if push_child.len() > 0 {
if let Some(grandparent) = push_child[0].node_mut(self) {
grandparent.put_child(&node_ref);
}
if let Some(node) = node_ref.node_mut(self) {
node.parent = Some(push_child[0].clone());
}
} else {
self.push_root(&node_ref.id);
if let Some(node) = node_ref.node_mut(self) {
node.parent = None;
}
}
res.append(&mut push_child);
res.append(&mut remove_child);
res.push(node_ref.clone());
}
for nref in &res {
if let Some(node) = nref.node_mut(self) {
node.invalidate_all();
}
}
res
}
pub fn move_node(&mut self, source: impl IntoNodeRef, destination: impl IntoNodeRef) -> Vec<SNodeRef> {
let node_ref = source.node_ref();
let destination = destination.node_ref();
if !node_ref.exists(self) || !destination.exists(self) { return vec![]; }
let mut res: Vec<SNodeRef> = vec![];
res.push(destination.clone());
res.push(node_ref.clone());
if let Some(new_parent) = destination.node_mut(self) {
new_parent.put_child(&node_ref);
}
let mut existing_parent: Option<SNodeRef> = None;
if let Some(node) = node_ref.node_mut(self) {
if node.parent.is_some() {
existing_parent = node.parent.clone();
}
node.parent = Some(destination.clone());
}
if let Some(old_parent) = existing_parent {
if let Some(old_parent) = old_parent.node_mut(self) {
old_parent.remove_child(&node_ref);
}
res.push(old_parent);
} else {
self.remove_root(&node_ref.id);
}
for nref in &res {
if let Some(node) = nref.node_mut(self) {
node.invalidate_all();
}
}
res
}
pub fn absorb_external_node(&mut self, graph: &Self, node: &SNode, onto: &SNodeRef) {
for dref in &node.data {
if let Some(data) = dref.data(graph) {
let mut data = data.clone();
data.invalidate(DATA_DIRTY_NODES);
self.put_data(onto, data);
}
}
for child_ref in &node.children {
if let Some(child) = child_ref.node(graph) {
self.insert_external_node(graph, child, Some(onto), None);
}
}
}
pub fn insert_external_node(&mut self, graph: &Self, node: &SNode, parent: Option<&SNodeRef>, rename: Option<String>) {
let mut cloned = node.clone();
if let Some(new_name) = rename {
cloned.name = new_name;
}
let clone = self.insert_node_raw(cloned, parent);
let mut to_remove = Vec::new();
for dref in &node.data {
if let Some(data) = dref.data(graph) {
let mut data = data.clone();
data.invalidate(DATA_DIRTY_NODES);
self.put_data(&clone, data);
} else {
to_remove.push(dref.clone());
}
}
if to_remove.len() > 0 {
if let Some(clone_node) = clone.node_mut(self) {
for data_ref in &to_remove {
clone_node.remove_data(data_ref);
}
}
}
for child_ref in &node.children {
if let Some(child) = child_ref.node(graph) {
self.insert_external_node(graph, child, Some(&clone), None);
}
}
}
pub fn put_data(&mut self, node: impl IntoNodeRef, mut data: SData) -> Option<SDataRef> {
let node_ref = node.node_ref();
if let Some(node) = node_ref.node_mut(self) {
let res = data.data_ref();
if node.put_data(&res) {
data.new_reference(node_ref.clone());
}
self.data.set(&data.id.clone(), data);
return Some(res);
}
None
}
pub fn put_data_ref(&mut self, node: impl IntoNodeRef, data: impl IntoDataRef) -> bool {
let node_ref = node.node_ref();
let data_ref = data.data_ref();
if !data_ref.exists(self) { return false; }
let mut added = false;
if let Some(node) = node_ref.node_mut(self) {
if node.put_data(&data_ref) {
added = true;
}
}
if added {
if let Some(data) = data_ref.data_mut(self) {
data.new_reference(node_ref.clone());
}
return true;
}
false
}
pub fn remove_data(&mut self, to_ref: impl IntoDataRef, node: Option<&SNodeRef>) -> bool {
let data_ref = to_ref.data_ref();
if !data_ref.exists(self) { return false; }
let mut res = false;
let mut remove_completely = true;
if let Some(node) = node {
remove_completely = false;
let mut removed = false;
if let Some(node) = node.node_mut(self) {
if node.remove_data(&data_ref) {
removed = true;
}
}
if removed {
res = true;
if let Some(data) = data_ref.data_mut(self) {
data.ref_removed(node);
remove_completely = data.ref_count() < 1;
}
}
}
if remove_completely {
if node.is_none() {
let mut removed_from: Vec<SNodeRef> = Vec::new();
for (_, node) in &mut self.nodes.store {
if node.remove_data(&data_ref) {
removed_from.push(node.node_ref());
}
}
if let Some(data) = data_ref.data_mut(self) {
for nref in &removed_from {
data.ref_removed(nref)
}
}
}
res = self.data.remove(&data_ref.id);
}
res
}
pub fn flush_node_deadpool(&mut self) -> Vec<SNode> {
self.nodes.flush_deadpool()
}
pub fn flush_data_deadpool(&mut self) -> Vec<SData> {
self.data.flush_deadpool()
}
pub fn flush_nodes(&mut self, limit: i32) -> Vec<&mut SNode> {
self.nodes.flush(limit)
}
pub fn flush_data(&mut self, limit: i32) -> Vec<&mut SData> {
self.data.flush(limit)
}
pub fn absorb_graph(&mut self, other: Self) {
for root_node in other.roots {
self.push_root(&root_node.id);
}
for (id, node) in other.nodes.store {
self.nodes.set(&id, node);
}
for (id, data) in other.data.store {
self.data.set(&id, data);
}
}
fn get_node_collisions(&self, node: &SNodeRef, other: &Self, other_node: &SNodeRef) -> (Vec<SNodeRef>, Vec<SNodeRef>) {
let mut node_collisions = Vec::new();
let mut other_collisions = Vec::new();
if let Some(node) = node.node(&self) {
if let Some(other_node) = other_node.node(&other) {
for child_ref in &node.children {
if let Some(child) = child_ref.node(&self) {
for other_child_ref in &other_node.children {
if let Some(other_child) = other_child_ref.node(&other) {
if child.name == other_child.name {
node_collisions.push(child_ref.clone());
other_collisions.push(other_child_ref.clone());
let (mut nodes, mut others) = self.get_node_collisions(child_ref, other, other_child_ref);
node_collisions.append(&mut nodes);
other_collisions.append(&mut others);
}
}
}
}
}
}
}
return (node_collisions, other_collisions);
}
pub fn get_collisions(&self, other: &Self) -> (Vec<SNodeRef>, Vec<SNodeRef>) {
let mut node_collisions = Vec::new();
let mut other_collisions = Vec::new();
for root_ref in &self.roots {
if let Some(root) = root_ref.node(&self) {
for other_root_ref in &other.roots {
if let Some(other_root) = other_root_ref.node(&other) {
if root.name == other_root.name {
node_collisions.push(root_ref.clone());
other_collisions.push(other_root_ref.clone());
let (mut nodes, mut others) = self.get_node_collisions(root_ref, other, other_root_ref);
node_collisions.append(&mut nodes);
other_collisions.append(&mut others);
}
}
}
}
}
return (node_collisions, other_collisions);
}
pub fn absorb_merge(&mut self, mut other: Self, add_unique_other: bool,
mut collision_handler: impl FnMut(&mut Self, &mut Self, &mut (SNodeRef, SNodeRef)) -> Result<(), SError>,
mut unique_self_handler: impl FnMut(&mut Self, &SNodeRef) -> Result<(), SError>) -> Result<(), SError> {
let collisions = self.get_collisions(&other);
for index in 0..collisions.0.len() {
if index < collisions.1.len() {
let mut collide = (collisions.0[index].clone(), collisions.1[index].clone());
collision_handler(self, &mut other, &mut collide)?;
}
}
if add_unique_other {
let other_collided: HashSet<SNodeRef> = collisions.1.iter().cloned().collect();
for (_, node) in other.nodes.store {
if !other_collided.contains(&node.node_ref()) {
for dref in &node.data {
if let Some(data) = other.data.store.remove(&dref.id) {
self.data.set(&data.id.clone(), data);
}
}
if node.parent.is_none() {
self.roots.push(node.node_ref());
}
self.nodes.set(&node.id.clone(), node);
}
}
}
let self_collided: HashSet<SNodeRef> = collisions.0.iter().cloned().collect();
let mut unique_self = Vec::new();
for (_, node) in &self.nodes.store {
if !self_collided.contains(&node.node_ref()) {
unique_self.push(node.node_ref());
}
}
for unique_ref in unique_self {
unique_self_handler(self, &unique_ref)?;
}
Ok(())
}
pub fn default_absorb_merge(&mut self, other: Self) -> Result<(), SError> {
self.absorb_merge(other, true,
|graph, other, nodes| {
let mut data = HashSet::new();
let mut children = Vec::new(); let mut other_fields = Vec::new();
if let Some(node) = nodes.1.node(other) {
for dref in &node.data {
data.insert(dref.clone());
if SData::type_of::<SField>(&other, dref) {
other_fields.push(dref.clone());
}
}
children.append(&mut node.children.iter().cloned().collect());
}
SField::merge_fields(graph, &nodes.0, &other, &other_fields)?;
if let Some(node) = nodes.0.node_mut(graph) {
for child in &children {
node.put_child(child);
}
}
for dref in &data {
if !SData::type_of::<SField>(&other, dref) {
if let Some(data) = dref.data(other) {
graph.put_data(&nodes.0, data.clone());
}
}
}
Ok(())
},
|_graph, _node| {
Ok(())
})?;
Ok(())
}
pub fn dump(&self, data: bool) {
println!("Dump SGraph: {} (ver: {:?})", &self.name, &self.version);
for root_ref in &self.roots {
if let Some(root) = root_ref.node(self) {
println!("{}", root.dump(self, 0, data));
}
}
println!("END DUMP");
}
}
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize};
use crate::{Data, SData, SVersion};
use super::SGraph;
#[derive(Deserialize, Serialize, Debug, Clone)]
struct MyData {
name: String,
}
#[typetag::serde(name = "Test::MyData")]
impl Data for MyData {}
#[test]
fn default_constructor() {
let graph = SGraph::default();
assert!(graph.id.len() > 0);
assert!(graph.name.len() > 0);
assert_eq!(graph.root_count(), 0);
assert_eq!(graph.nodes.store.len(), 0);
assert_eq!(graph.data.store.len(), 0);
assert_eq!(graph.version, SVersion::default());
}
#[test]
fn construct_graph() {
let mut graph = SGraph::new("graph");
let cj;
let amelia;
let root = graph.insert_node("root", None);
{
let base= graph.insert_node("base", Some(&root));
{
cj = graph.put_data(&base, SData::new(Box::new(MyData { name: "CJ".to_owned() })));
}
let top = graph.insert_node("top", Some(&root));
{
amelia = graph.put_data(&top, SData::new(Box::new(MyData { name: "Amelia".to_owned() })));
}
}
let binary = bincode::serialize(&graph).unwrap();
let gph = bincode::deserialize::<SGraph>(&binary).unwrap();
let cj = SData::get::<MyData>(&gph, &cj).unwrap();
let amelia = SData::get::<MyData>(&gph, &amelia).unwrap();
assert_eq!(cj.name, "CJ");
assert_eq!(amelia.name, "Amelia");
}
#[test]
fn insert_root() {
let mut graph = SGraph::new("graph");
let cj;
let amelia;
let root = graph.insert_root("root");
{
let base= graph.insert_node("base", Some(&root));
{
cj = graph.put_data(&base, SData::new(Box::new(MyData { name: "CJ".to_owned() })));
}
let top = graph.insert_node("top", Some(&root));
{
amelia = graph.put_data(&top, SData::new(Box::new(MyData { name: "Amelia".to_owned() })));
}
}
let binary = bincode::serialize(&graph).unwrap();
let mut gph = bincode::deserialize::<SGraph>(&binary).unwrap();
{
let cj = SData::get::<MyData>(&gph, &cj).unwrap();
let amelia = SData::get::<MyData>(&gph, &amelia).unwrap();
assert_eq!(cj.name, "CJ");
assert_eq!(amelia.name, "Amelia");
}
if let Some(mut_cj) = SData::get_mut::<MyData>(&mut gph, &cj) {
mut_cj.name = "DUDE".to_string();
}
{
let cj = SData::get::<MyData>(&gph, &cj).unwrap();
let amelia = SData::get::<MyData>(&gph, &amelia).unwrap();
assert_eq!(cj.name, "DUDE");
assert_eq!(amelia.name, "Amelia");
}
}
#[test]
fn node_path() {
let mut graph = SGraph::default();
let root = graph.insert_root("root");
let base;
let top;
{
base = graph.insert_node("base", Some(&root));
{
graph.insert_node("a", Some(&base));
graph.insert_node("b", Some(&base));
graph.insert_node("b", Some(&base));
}
top = graph.insert_node("top", Some(&root));
{
graph.insert_node("a", Some(&top));
graph.insert_node("b", Some(&top));
}
}
assert!(graph.node_ref("root/base/b", Some(&root)).is_some());
assert!(graph.node_ref("root/top/b", Some(&root)).is_some());
assert!(graph.node_ref("base/b", Some(&root)).is_some());
assert!(graph.node_ref("top/b", Some(&root)).is_some());
assert!(graph.node_ref("b", Some(&root)).is_none());
assert!(graph.node_ref("self/base/self/super/base/a/self", Some(&root)).is_some());
assert!(graph.node_ref("./top/../top/a", Some(&root)).is_some());
assert!(graph.node_ref("base/a", Some(&root)).is_some());
assert!(graph.node_ref("top/a/.", Some(&root)).is_some());
assert!(graph.node_ref("a", Some(&root)).is_none());
assert!(graph.node_ref("root/top/super/top", Some(&root)).is_some());
assert!(graph.node_ref("top", Some(&root)).is_some());
assert!(graph.node_ref("self/self/self/base", Some(&root)).is_some());
assert!(graph.node_ref("base", Some(&root)).is_some());
assert!(graph.node_ref("root/base/b", None).is_some());
assert!(graph.node_ref("root/top/b", None).is_some());
assert!(graph.node_ref("base/b", None).is_some());
assert!(graph.node_ref("top/b", None).is_some());
assert!(graph.node_ref("b", None).is_some());
assert!(graph.node_ref("root/base/a", None).is_some());
assert!(graph.node_ref("root/top/a", None).is_some());
assert!(graph.node_ref("base/a", None).is_some());
assert!(graph.node_ref("top/a", None).is_some());
assert!(graph.node_ref("a", None).is_some());
assert!(graph.node_ref("root/top", None).is_some());
assert!(graph.node_ref("top", None).is_some());
assert!(graph.node_ref("root/base", None).is_some());
assert!(graph.node_ref("base", None).is_some());
assert!(graph.node_ref("a", Some(&base)).is_some());
assert!(graph.node_ref("a", Some(&top)).is_some());
assert!(graph.node_ref("b", Some(&base)).is_some());
assert!(graph.node_ref("b", Some(&top)).is_some());
assert_eq!(graph.node_refs("base/b").len(), 2);
assert_eq!(graph.node_refs("root/base/b").len(), 2);
assert_eq!(graph.node_refs("base/a").len(), 1);
assert_eq!(graph.node_refs("top/a").len(), 1);
assert_eq!(graph.node_refs("top/b").len(), 1);
assert_eq!(graph.node_refs("root/top/a").len(), 1);
assert_eq!(graph.node_refs("root/top/b").len(), 1);
assert_eq!(graph.node_refs("top").len(), 1);
assert_eq!(graph.node_refs("base").len(), 1);
assert_eq!(graph.node_refs("root/top").len(), 1);
assert_eq!(graph.node_refs("root/base").len(), 1);
}
}