Skip to main content

paladin_core/base/entity/
node.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use std::hash::{Hash, Hasher};
4use uuid::Uuid;
5
6#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
7pub struct Node<T> {
8    pub uuid: Uuid,
9    pub created: DateTime<Utc>,
10    pub modified: DateTime<Utc>,
11    pub node: T,
12    pub name: Option<String>,
13    pub version: bool,
14}
15
16impl<T> Hash for Node<T>
17where
18    T: Hash,
19{
20    fn hash<H: Hasher>(&self, state: &mut H) {
21        self.uuid.hash(state);
22        self.name.hash(state);
23        self.node.hash(state);
24    }
25}
26
27impl<T> Node<T> {
28    pub fn new(node: T, name: Option<String>) -> Self {
29        let now = Utc::now();
30        Self {
31            uuid: Uuid::new_v4(),
32            created: now,
33            modified: now,
34            node,
35            name,
36            version: true,
37        }
38    }
39
40    pub fn new_with_uuid(uuid: Uuid, node: T, name: Option<String>) -> Self {
41        let now = Utc::now();
42        Self {
43            uuid,
44            created: now,
45            modified: now,
46            node,
47            name,
48            version: true,
49        }
50    }
51
52    pub fn update(&mut self, new_data: T) {
53        self.node = new_data;
54        self.modified = Utc::now();
55    }
56
57    pub fn set_name(&mut self, name: Option<String>) {
58        self.name = name;
59        self.modified = Utc::now();
60    }
61
62    pub fn enable_versioning(&mut self) {
63        self.version = true;
64        self.modified = Utc::now();
65    }
66
67    pub fn disable_versioning(&mut self) {
68        self.version = false;
69        self.modified = Utc::now();
70    }
71
72    pub fn is_versioning_enabled(&self) -> bool {
73        self.version
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80    use serde::{Deserialize, Serialize};
81
82    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
83    struct TestData {
84        value: String,
85        number: u32,
86    }
87
88    #[test]
89    fn test_node_creation() {
90        let test_data = TestData {
91            value: "test".to_string(),
92            number: 42,
93        };
94
95        let node = Node::new(test_data.clone(), Some("Test Node".to_string()));
96
97        assert_eq!(node.node, test_data);
98        assert_eq!(node.name, Some("Test Node".to_string()));
99        assert!(node.version);
100        assert_eq!(node.created, node.modified);
101    }
102
103    #[test]
104    fn test_node_update() {
105        let initial_data = TestData {
106            value: "initial".to_string(),
107            number: 1,
108        };
109
110        let mut node = Node::new(initial_data, None);
111        let initial_modified = node.modified;
112
113        std::thread::sleep(std::time::Duration::from_millis(1));
114
115        let new_data = TestData {
116            value: "updated".to_string(),
117            number: 2,
118        };
119
120        node.update(new_data.clone());
121
122        assert_eq!(node.node, new_data);
123        assert!(node.modified > initial_modified);
124    }
125
126    #[test]
127    fn test_versioning_control() {
128        let test_data = TestData {
129            value: "test".to_string(),
130            number: 42,
131        };
132
133        let mut node = Node::new(test_data, None);
134
135        assert!(node.is_versioning_enabled());
136
137        node.disable_versioning();
138        assert!(!node.is_versioning_enabled());
139
140        node.enable_versioning();
141        assert!(node.is_versioning_enabled());
142    }
143
144    #[test]
145    fn test_node_hash() {
146        let test_data1 = TestData {
147            value: "test1".to_string(),
148            number: 1,
149        };
150
151        let test_data2 = TestData {
152            value: "test2".to_string(),
153            number: 2,
154        };
155
156        let node1 = Node::new(test_data1, Some("Node 1".to_string()));
157        let node2 = Node::new(test_data2, Some("Node 2".to_string()));
158
159        // Different nodes should have different hashes
160        let mut hasher1 = std::collections::hash_map::DefaultHasher::new();
161        let mut hasher2 = std::collections::hash_map::DefaultHasher::new();
162
163        node1.hash(&mut hasher1);
164        node2.hash(&mut hasher2);
165
166        assert_ne!(hasher1.finish(), hasher2.finish());
167    }
168
169    #[test]
170    fn test_node_serialization() -> Result<(), Box<dyn std::error::Error>> {
171        let test_data = TestData {
172            value: "serialize_test".to_string(),
173            number: 100,
174        };
175
176        let node = Node::new(test_data, Some("Serialization Test".to_string()));
177
178        // Test serialization
179        let serialized = serde_json::to_string(&node)?;
180        assert!(!serialized.is_empty());
181
182        // Test deserialization
183        let deserialized: Node<TestData> = serde_json::from_str(&serialized)?;
184        assert_eq!(node, deserialized);
185
186        Ok(())
187    }
188}