1use crate::errors::{Result, RuleEngineError};
7use crate::rete::facts::TypedFacts;
8use std::collections::HashMap;
9
10#[derive(Debug, Clone)]
12pub struct FactInstance {
13 pub fact_type: String,
15 pub data: TypedFacts,
17}
18
19impl FactInstance {
20 pub fn new(fact_type: impl Into<String>, data: TypedFacts) -> Self {
22 Self {
23 fact_type: fact_type.into(),
24 data,
25 }
26 }
27}
28
29#[derive(Debug, Clone)]
31pub struct Deffacts {
32 pub name: String,
34 pub facts: Vec<FactInstance>,
36 pub description: Option<String>,
38}
39
40impl Deffacts {
41 pub fn new(name: impl Into<String>) -> Self {
43 Self {
44 name: name.into(),
45 facts: Vec::new(),
46 description: None,
47 }
48 }
49
50 pub fn add_fact(&mut self, fact_type: impl Into<String>, data: TypedFacts) {
52 self.facts.push(FactInstance::new(fact_type, data));
53 }
54
55 pub fn set_description(&mut self, description: impl Into<String>) {
57 self.description = Some(description.into());
58 }
59
60 pub fn fact_count(&self) -> usize {
62 self.facts.len()
63 }
64
65 pub fn is_empty(&self) -> bool {
67 self.facts.is_empty()
68 }
69}
70
71#[derive(Debug, Clone)]
74pub struct DeffactsRegistry {
75 deffacts: HashMap<String, Deffacts>,
76}
77
78impl DeffactsRegistry {
79 pub fn new() -> Self {
81 Self {
82 deffacts: HashMap::new(),
83 }
84 }
85
86 pub fn register(&mut self, deffacts: Deffacts) -> Result<()> {
88 let name = deffacts.name.clone();
89
90 if self.deffacts.contains_key(&name) {
91 return Err(RuleEngineError::EvaluationError {
92 message: format!("Deffacts '{}' already exists", name),
93 });
94 }
95
96 self.deffacts.insert(name, deffacts);
97 Ok(())
98 }
99
100 pub fn register_or_replace(&mut self, deffacts: Deffacts) {
102 let name = deffacts.name.clone();
103 self.deffacts.insert(name, deffacts);
104 }
105
106 pub fn get(&self, name: &str) -> Option<&Deffacts> {
108 self.deffacts.get(name)
109 }
110
111 pub fn get_mut(&mut self, name: &str) -> Option<&mut Deffacts> {
113 self.deffacts.get_mut(name)
114 }
115
116 pub fn exists(&self, name: &str) -> bool {
118 self.deffacts.contains_key(name)
119 }
120
121 pub fn remove(&mut self, name: &str) -> Result<Deffacts> {
123 self.deffacts
124 .remove(name)
125 .ok_or_else(|| RuleEngineError::EvaluationError {
126 message: format!("Deffacts '{}' not found", name),
127 })
128 }
129
130 pub fn list_deffacts(&self) -> Vec<String> {
132 self.deffacts.keys().cloned().collect()
133 }
134
135 pub fn get_all_facts(&self) -> Vec<(String, FactInstance)> {
137 let mut all_facts = Vec::new();
138
139 for (deffacts_name, deffacts) in &self.deffacts {
140 for fact in &deffacts.facts {
141 all_facts.push((deffacts_name.clone(), fact.clone()));
142 }
143 }
144
145 all_facts
146 }
147
148 pub fn total_fact_count(&self) -> usize {
150 self.deffacts.values().map(|d| d.fact_count()).sum()
151 }
152
153 pub fn clear(&mut self) {
155 self.deffacts.clear();
156 }
157
158 pub fn len(&self) -> usize {
160 self.deffacts.len()
161 }
162
163 pub fn is_empty(&self) -> bool {
165 self.deffacts.is_empty()
166 }
167}
168
169impl Default for DeffactsRegistry {
170 fn default() -> Self {
171 Self::new()
172 }
173}
174
175pub struct DeffactsBuilder {
177 name: String,
178 facts: Vec<FactInstance>,
179 description: Option<String>,
180}
181
182impl DeffactsBuilder {
183 pub fn new(name: impl Into<String>) -> Self {
185 Self {
186 name: name.into(),
187 facts: Vec::new(),
188 description: None,
189 }
190 }
191
192 pub fn add_fact(mut self, fact_type: impl Into<String>, data: TypedFacts) -> Self {
194 self.facts.push(FactInstance::new(fact_type, data));
195 self
196 }
197
198 pub fn add_facts(mut self, fact_type: impl Into<String>, facts: Vec<TypedFacts>) -> Self {
200 let fact_type_str = fact_type.into();
201 for data in facts {
202 self.facts
203 .push(FactInstance::new(fact_type_str.clone(), data));
204 }
205 self
206 }
207
208 pub fn with_description(mut self, description: impl Into<String>) -> Self {
210 self.description = Some(description.into());
211 self
212 }
213
214 pub fn build(self) -> Deffacts {
216 Deffacts {
217 name: self.name,
218 facts: self.facts,
219 description: self.description,
220 }
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227 use crate::rete::facts::FactValue;
228
229 #[test]
230 fn test_create_fact_instance() {
231 let mut data = TypedFacts::new();
232 data.set("name", FactValue::String("John".to_string()));
233 data.set("age", FactValue::Integer(30));
234
235 let fact = FactInstance::new("Person", data);
236 assert_eq!(fact.fact_type, "Person");
237 assert_eq!(
238 fact.data.get("name"),
239 Some(&FactValue::String("John".to_string()))
240 );
241 }
242
243 #[test]
244 fn test_deffacts_basic() {
245 let mut deffacts = Deffacts::new("initial-data");
246
247 let mut person_data = TypedFacts::new();
248 person_data.set("name", FactValue::String("Alice".to_string()));
249
250 deffacts.add_fact("Person", person_data);
251 deffacts.set_description("Initial person data");
252
253 assert_eq!(deffacts.name, "initial-data");
254 assert_eq!(deffacts.fact_count(), 1);
255 assert!(!deffacts.is_empty());
256 assert_eq!(
257 deffacts.description,
258 Some("Initial person data".to_string())
259 );
260 }
261
262 #[test]
263 fn test_registry_register() {
264 let mut registry = DeffactsRegistry::new();
265
266 let mut deffacts = Deffacts::new("test");
267 let mut data = TypedFacts::new();
268 data.set("value", FactValue::Integer(42));
269 deffacts.add_fact("Config", data);
270
271 registry.register(deffacts).unwrap();
272
273 assert!(registry.exists("test"));
274 assert_eq!(registry.len(), 1);
275 }
276
277 #[test]
278 fn test_registry_duplicate_error() {
279 let mut registry = DeffactsRegistry::new();
280
281 let deffacts1 = Deffacts::new("test");
282 let deffacts2 = Deffacts::new("test");
283
284 registry.register(deffacts1).unwrap();
285 let result = registry.register(deffacts2);
286
287 assert!(result.is_err());
288 }
289
290 #[test]
291 fn test_registry_register_or_replace() {
292 let mut registry = DeffactsRegistry::new();
293
294 let mut deffacts1 = Deffacts::new("test");
295 let mut data1 = TypedFacts::new();
296 data1.set("version", FactValue::Integer(1));
297 deffacts1.add_fact("Config", data1);
298
299 let mut deffacts2 = Deffacts::new("test");
300 let mut data2 = TypedFacts::new();
301 data2.set("version", FactValue::Integer(2));
302 deffacts2.add_fact("Config", data2);
303
304 registry.register_or_replace(deffacts1);
305 registry.register_or_replace(deffacts2);
306
307 assert_eq!(registry.len(), 1);
308 let deffacts = registry.get("test").unwrap();
309 assert_eq!(deffacts.fact_count(), 1);
310 }
311
312 #[test]
313 fn test_registry_get_all_facts() {
314 let mut registry = DeffactsRegistry::new();
315
316 let mut deffacts1 = Deffacts::new("set1");
318 let mut data1 = TypedFacts::new();
319 data1.set("name", FactValue::String("Alice".to_string()));
320 deffacts1.add_fact("Person", data1);
321
322 let mut data2 = TypedFacts::new();
323 data2.set("name", FactValue::String("Bob".to_string()));
324 deffacts1.add_fact("Person", data2);
325
326 let mut deffacts2 = Deffacts::new("set2");
328 let mut data3 = TypedFacts::new();
329 data3.set("debug", FactValue::Boolean(true));
330 deffacts2.add_fact("Config", data3);
331
332 registry.register(deffacts1).unwrap();
333 registry.register(deffacts2).unwrap();
334
335 let all_facts = registry.get_all_facts();
336 assert_eq!(all_facts.len(), 3);
337 assert_eq!(registry.total_fact_count(), 3);
338 }
339
340 #[test]
341 fn test_registry_remove() {
342 let mut registry = DeffactsRegistry::new();
343
344 let deffacts = Deffacts::new("temp");
345 registry.register(deffacts).unwrap();
346
347 assert!(registry.exists("temp"));
348
349 let removed = registry.remove("temp").unwrap();
350 assert_eq!(removed.name, "temp");
351 assert!(!registry.exists("temp"));
352 }
353
354 #[test]
355 fn test_registry_list_deffacts() {
356 let mut registry = DeffactsRegistry::new();
357
358 registry.register(Deffacts::new("set1")).unwrap();
359 registry.register(Deffacts::new("set2")).unwrap();
360 registry.register(Deffacts::new("set3")).unwrap();
361
362 let list = registry.list_deffacts();
363 assert_eq!(list.len(), 3);
364 assert!(list.contains(&"set1".to_string()));
365 assert!(list.contains(&"set2".to_string()));
366 assert!(list.contains(&"set3".to_string()));
367 }
368
369 #[test]
370 fn test_registry_clear() {
371 let mut registry = DeffactsRegistry::new();
372
373 registry.register(Deffacts::new("set1")).unwrap();
374 registry.register(Deffacts::new("set2")).unwrap();
375
376 assert_eq!(registry.len(), 2);
377
378 registry.clear();
379
380 assert_eq!(registry.len(), 0);
381 assert!(registry.is_empty());
382 }
383
384 #[test]
385 fn test_builder_basic() {
386 let mut data = TypedFacts::new();
387 data.set("name", FactValue::String("Charlie".to_string()));
388 data.set("age", FactValue::Integer(25));
389
390 let deffacts = DeffactsBuilder::new("people")
391 .add_fact("Person", data)
392 .with_description("Initial people data")
393 .build();
394
395 assert_eq!(deffacts.name, "people");
396 assert_eq!(deffacts.fact_count(), 1);
397 assert_eq!(
398 deffacts.description,
399 Some("Initial people data".to_string())
400 );
401 }
402
403 #[test]
404 fn test_builder_multiple_facts() {
405 let mut person1 = TypedFacts::new();
406 person1.set("name", FactValue::String("Alice".to_string()));
407
408 let mut person2 = TypedFacts::new();
409 person2.set("name", FactValue::String("Bob".to_string()));
410
411 let mut config = TypedFacts::new();
412 config.set("debug", FactValue::Boolean(true));
413
414 let deffacts = DeffactsBuilder::new("startup")
415 .add_fact("Person", person1)
416 .add_fact("Person", person2)
417 .add_fact("Config", config)
418 .build();
419
420 assert_eq!(deffacts.fact_count(), 3);
421 }
422
423 #[test]
424 fn test_builder_add_facts_batch() {
425 let mut person1 = TypedFacts::new();
426 person1.set("name", FactValue::String("Alice".to_string()));
427
428 let mut person2 = TypedFacts::new();
429 person2.set("name", FactValue::String("Bob".to_string()));
430
431 let people = vec![person1, person2];
432
433 let deffacts = DeffactsBuilder::new("batch-people")
434 .add_facts("Person", people)
435 .build();
436
437 assert_eq!(deffacts.fact_count(), 2);
438 assert_eq!(deffacts.facts[0].fact_type, "Person");
439 assert_eq!(deffacts.facts[1].fact_type, "Person");
440 }
441
442 #[test]
443 fn test_integration_with_registry() {
444 let mut registry = DeffactsRegistry::new();
445
446 let mut person_data = TypedFacts::new();
448 person_data.set("name", FactValue::String("Admin".to_string()));
449 person_data.set("role", FactValue::String("administrator".to_string()));
450
451 let mut config_data = TypedFacts::new();
452 config_data.set("max_users", FactValue::Integer(1000));
453 config_data.set("debug_mode", FactValue::Boolean(false));
454
455 let deffacts = DeffactsBuilder::new("system-startup")
456 .add_fact("User", person_data)
457 .add_fact("SystemConfig", config_data)
458 .with_description("System initialization facts")
459 .build();
460
461 registry.register(deffacts).unwrap();
463
464 assert!(registry.exists("system-startup"));
466 let retrieved = registry.get("system-startup").unwrap();
467 assert_eq!(retrieved.fact_count(), 2);
468 assert_eq!(
469 retrieved.description,
470 Some("System initialization facts".to_string())
471 );
472 }
473}