use super::super::{CRDT, Mergeable, ReplicaId};
use super::{config::TreeConfig, error::TreeError, types::{NodeId, TreeNode}};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AddWinsTree<T> {
config: TreeConfig,
nodes: HashMap<NodeId, TreeNode<T>>,
replica: ReplicaId,
}
impl<T: Clone + PartialEq + Eq + Send + Sync> AddWinsTree<T> {
pub fn new(replica: ReplicaId) -> Self {
Self {
config: TreeConfig::default(),
nodes: HashMap::new(),
replica,
}
}
pub fn with_config(replica: ReplicaId, config: TreeConfig) -> Self {
Self {
config,
nodes: HashMap::new(),
replica,
}
}
pub fn add_root(&mut self, value: T, timestamp: u64) -> NodeId {
let node = TreeNode::new(value, self.replica, timestamp);
let id = node.id.clone();
self.nodes.insert(id.clone(), node);
id
}
pub fn add_child(&mut self, parent_id: &NodeId, value: T, timestamp: u64) -> Result<NodeId, TreeError> {
if !self.nodes.contains_key(parent_id) {
return Err(TreeError::new("Parent node not found".to_string()));
}
let node = TreeNode::new_child(value, self.replica, timestamp, parent_id.clone());
let id = node.id.clone();
self.nodes.insert(id.clone(), node);
if let Some(parent) = self.nodes.get_mut(parent_id) {
parent.add_child(id.clone());
}
Ok(id)
}
pub fn update(&mut self, id: &NodeId, value: T, timestamp: u64) -> Result<(), TreeError> {
if let Some(node) = self.nodes.get_mut(id) {
node.value = value;
node.mark_modified(self.replica, timestamp);
Ok(())
} else {
Err(TreeError::new("Node not found".to_string()))
}
}
pub fn remove(&mut self, id: &NodeId, timestamp: u64) -> Result<(), TreeError> {
if let Some(node) = self.nodes.get_mut(id) {
node.mark_deleted(self.replica, timestamp);
Ok(())
} else {
Err(TreeError::new("Node not found".to_string()))
}
}
pub fn move_node(&mut self, id: &NodeId, new_parent_id: &NodeId) -> Result<(), TreeError> {
if !self.nodes.contains_key(id) || !self.nodes.contains_key(new_parent_id) {
return Err(TreeError::new("Node not found".to_string()));
}
let old_parent_id = self.nodes.get(id).and_then(|node| node.parent.clone());
if let Some(old_parent_id) = old_parent_id {
if let Some(old_parent) = self.nodes.get_mut(&old_parent_id) {
old_parent.remove_child(id);
}
}
if let Some(node) = self.nodes.get_mut(id) {
node.parent = Some(new_parent_id.clone());
}
if let Some(new_parent) = self.nodes.get_mut(new_parent_id) {
new_parent.add_child(id.clone());
}
Ok(())
}
pub fn get(&self, id: &NodeId) -> Option<&TreeNode<T>> {
self.nodes.get(id)
}
pub fn visible_nodes(&self) -> Vec<&TreeNode<T>> {
self.nodes
.values()
.filter(|n| !n.metadata.deleted)
.collect()
}
pub fn all_nodes(&self) -> Vec<&TreeNode<T>> {
self.nodes.values().collect()
}
pub fn roots(&self) -> Vec<&TreeNode<T>> {
self.nodes
.values()
.filter(|n| n.parent.is_none() && !n.metadata.deleted)
.collect()
}
pub fn children(&self, id: &NodeId) -> Vec<&TreeNode<T>> {
if let Some(node) = self.nodes.get(id) {
node.children
.iter()
.filter_map(|child_id| self.nodes.get(child_id))
.filter(|n| !n.metadata.deleted)
.collect()
} else {
Vec::new()
}
}
pub fn descendants(&self, id: &NodeId) -> Vec<&TreeNode<T>> {
let mut descendants = Vec::new();
self.collect_descendants(id, &mut descendants);
descendants
}
fn collect_descendants<'a>(&'a self, id: &NodeId, descendants: &mut Vec<&'a TreeNode<T>>) {
if let Some(node) = self.nodes.get(id) {
if !node.metadata.deleted {
for child_id in &node.children {
if let Some(child_node) = self.nodes.get(child_id) {
if !child_node.metadata.deleted {
descendants.push(child_node);
self.collect_descendants(child_id, descendants);
}
}
}
}
}
}
pub fn contains(&self, id: &NodeId) -> bool {
self.nodes.contains_key(id)
}
pub fn len(&self) -> usize {
self.visible_nodes().len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn clear(&mut self) {
self.nodes.clear();
}
pub fn config(&self) -> &TreeConfig {
&self.config
}
}
impl<T: Clone + PartialEq + Eq + Send + Sync> CRDT for AddWinsTree<T> {
fn replica_id(&self) -> &ReplicaId {
&self.replica
}
}
impl<T: Clone + PartialEq + Eq + Send + Sync> Mergeable for AddWinsTree<T> {
type Error = TreeError;
fn merge(&mut self, other: &Self) -> Result<(), Self::Error> {
for (id, node) in &other.nodes {
match self.nodes.get(id) {
Some(existing) => {
if node.metadata.modified_at > existing.metadata.modified_at {
self.nodes.insert(id.clone(), node.clone());
}
}
None => {
self.nodes.insert(id.clone(), node.clone());
}
}
}
Ok(())
}
fn has_conflict(&self, other: &Self) -> bool {
for (id, node) in &other.nodes {
if let Some(existing) = self.nodes.get(id) {
if node.metadata.modified_at == existing.metadata.modified_at
&& node.metadata.last_modified_by != existing.metadata.last_modified_by
{
return true;
}
}
}
false
}
}