use crate::graph::Id;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::fmt;
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct Relationship {
pub id: Id,
pub from_id: Id,
pub to_id: Id,
pub rel_type: String,
pub properties: HashMap<String, Value>,
}
impl fmt::Debug for Relationship {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let keys: Vec<&String> = self.properties.keys().collect();
f.debug_struct("Relationship")
.field("id", &self.id)
.field("from_id", &self.from_id)
.field("to_id", &self.to_id)
.field("rel_type", &self.rel_type)
.field("properties", &format!("[keys: {keys:?}]"))
.finish()
}
}
impl Relationship {
pub fn new(
id: Id,
from_id: Id,
to_id: Id,
rel_type: String,
properties: HashMap<String, Value>,
) -> Self {
Relationship {
id,
from_id,
to_id,
rel_type,
properties,
}
}
pub fn get_property(&self, key: &str) -> Option<&Value> {
self.properties.get(key)
}
pub fn set_property(&mut self, key: String, value: Value) {
self.properties.insert(key, value);
}
pub fn remove_property(&mut self, key: &str) -> Option<Value> {
self.properties.remove(key)
}
pub fn has_property(&self, key: &str) -> bool {
self.properties.contains_key(key)
}
pub fn property_keys(&self) -> Vec<&String> {
self.properties.keys().collect()
}
pub fn connects(&self, node1_id: Id, node2_id: Id) -> bool {
(self.from_id == node1_id && self.to_id == node2_id)
|| (self.from_id == node2_id && self.to_id == node1_id)
}
pub fn is_outgoing_from(&self, node_id: Id) -> bool {
self.from_id == node_id
}
pub fn is_incoming_to(&self, node_id: Id) -> bool {
self.to_id == node_id
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_relationship_creation() {
let properties = [("weight".to_string(), json!(0.8))].into();
let rel = Relationship::new(1, 10, 20, "KNOWS".to_string(), properties);
assert_eq!(rel.id, 1);
assert_eq!(rel.from_id, 10);
assert_eq!(rel.to_id, 20);
assert_eq!(rel.rel_type, "KNOWS");
assert_eq!(rel.get_property("weight"), Some(&json!(0.8)));
}
#[test]
fn test_relationship_direction() {
let rel = Relationship::new(1, 10, 20, "KNOWS".to_string(), HashMap::new());
assert!(rel.connects(10, 20));
assert!(rel.connects(20, 10));
assert!(!rel.connects(10, 30));
assert!(rel.is_outgoing_from(10));
assert!(!rel.is_outgoing_from(20));
assert!(rel.is_incoming_to(20));
assert!(!rel.is_incoming_to(10));
}
}