1use std::collections::HashMap;
26
27use crate::validation::rules::ValidationRule;
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum InheritanceMode {
32 Override,
34 Merge,
36 ChildFirst,
38 ParentFirst,
40}
41
42impl InheritanceMode {
43 pub fn description(&self) -> &'static str {
45 match self {
46 Self::Override => "Child rules override parent rules completely",
47 Self::Merge => "All parent and child rules apply (union)",
48 Self::ChildFirst => "Child rules applied first, then parent rules",
49 Self::ParentFirst => "Parent rules applied first, then child rules",
50 }
51 }
52}
53
54#[derive(Debug, Clone)]
56pub struct RuleMetadata {
57 pub rule: ValidationRule,
59 pub overrideable: bool,
61 pub inherited: bool,
63 pub source: String,
65}
66
67impl RuleMetadata {
68 pub fn new(rule: ValidationRule, source: impl Into<String>) -> Self {
70 Self {
71 rule,
72 overrideable: true,
73 inherited: false,
74 source: source.into(),
75 }
76 }
77
78 pub fn non_overrideable(mut self) -> Self {
80 self.overrideable = false;
81 self
82 }
83
84 pub fn as_inherited(mut self) -> Self {
86 self.inherited = true;
87 self
88 }
89}
90
91#[derive(Debug, Clone, Default)]
93pub struct ValidationRuleRegistry {
94 rules_by_type: HashMap<String, Vec<RuleMetadata>>,
96 parent_types: HashMap<String, String>,
98}
99
100impl ValidationRuleRegistry {
101 pub fn new() -> Self {
103 Self {
104 rules_by_type: HashMap::new(),
105 parent_types: HashMap::new(),
106 }
107 }
108
109 pub fn register_type(&mut self, type_name: impl Into<String>, rules: Vec<RuleMetadata>) {
111 self.rules_by_type.insert(type_name.into(), rules);
112 }
113
114 pub fn set_parent(&mut self, child_type: impl Into<String>, parent_type: impl Into<String>) {
116 self.parent_types.insert(child_type.into(), parent_type.into());
117 }
118
119 pub fn get_rules(&self, type_name: &str, mode: InheritanceMode) -> Vec<RuleMetadata> {
121 let mut rules = Vec::new();
122
123 if let Some(parent_name) = self.parent_types.get(type_name) {
125 let parent_rules = self.get_rules(parent_name, mode);
126 rules.extend(parent_rules.iter().map(|r| r.clone().as_inherited()));
127 }
128
129 if let Some(own_rules) = self.rules_by_type.get(type_name) {
131 match mode {
132 InheritanceMode::Override => {
133 return own_rules.clone();
135 },
136 InheritanceMode::Merge => {
137 for own_rule in own_rules {
139 rules.push(own_rule.clone());
140 }
141 },
142 InheritanceMode::ChildFirst => {
143 let mut result = own_rules.clone();
145 result.extend(rules);
146 return result;
147 },
148 InheritanceMode::ParentFirst => {
149 rules.extend(own_rules.clone());
151 },
152 }
153 }
154
155 rules
156 }
157
158 pub fn get_parent(&self, type_name: &str) -> Option<&str> {
160 self.parent_types.get(type_name).map(|s| s.as_str())
161 }
162
163 pub fn has_parent(&self, type_name: &str) -> bool {
165 self.parent_types.contains_key(type_name)
166 }
167}
168
169pub fn inherit_validation_rules(
179 parent_rules: &[ValidationRule],
180 child_rules: &[ValidationRule],
181 mode: InheritanceMode,
182) -> Vec<ValidationRule> {
183 match mode {
184 InheritanceMode::Override => {
185 child_rules.to_vec()
187 },
188 InheritanceMode::Merge => {
189 let mut combined = parent_rules.to_vec();
191 combined.extend_from_slice(child_rules);
192 combined
193 },
194 InheritanceMode::ChildFirst => {
195 let mut combined = child_rules.to_vec();
197 combined.extend_from_slice(parent_rules);
198 combined
199 },
200 InheritanceMode::ParentFirst => {
201 let mut combined = parent_rules.to_vec();
203 combined.extend_from_slice(child_rules);
204 combined
205 },
206 }
207}
208
209pub fn validate_inheritance(
219 _child_name: &str,
220 parent_name: &str,
221 registry: &ValidationRuleRegistry,
222) -> Result<(), String> {
223 if !registry.rules_by_type.contains_key(parent_name) {
225 return Err(format!("Parent type '{}' not found in validation registry", parent_name));
226 }
227
228 let mut visited = std::collections::HashSet::new();
230 let mut current = Some(parent_name.to_string());
231
232 while let Some(type_name) = current {
233 if visited.contains(&type_name) {
234 return Err(format!(
235 "Circular inheritance detected: '{}' inherits from itself",
236 type_name
237 ));
238 }
239 visited.insert(type_name.clone());
240
241 current = registry.get_parent(&type_name).map(|s| s.to_string());
242 }
243
244 Ok(())
245}
246
247#[cfg(test)]
248mod tests {
249 use super::*;
250
251 #[test]
252 fn test_override_mode() {
253 let parent = vec![
254 ValidationRule::Required,
255 ValidationRule::Length {
256 min: Some(5),
257 max: None,
258 },
259 ];
260 let child = vec![ValidationRule::Pattern {
261 pattern: "^[a-z]+$".to_string(),
262 message: None,
263 }];
264
265 let result = inherit_validation_rules(&parent, &child, InheritanceMode::Override);
266 assert_eq!(result.len(), 1);
267 assert!(matches!(result[0], ValidationRule::Pattern { .. }));
268 }
269
270 #[test]
271 fn test_merge_mode() {
272 let parent = vec![
273 ValidationRule::Required,
274 ValidationRule::Length {
275 min: Some(5),
276 max: None,
277 },
278 ];
279 let child = vec![ValidationRule::Pattern {
280 pattern: "^[a-z]+$".to_string(),
281 message: None,
282 }];
283
284 let result = inherit_validation_rules(&parent, &child, InheritanceMode::Merge);
285 assert_eq!(result.len(), 3);
286 }
287
288 #[test]
289 fn test_child_first_mode() {
290 let parent = vec![ValidationRule::Required];
291 let child = vec![ValidationRule::Pattern {
292 pattern: "^[a-z]+$".to_string(),
293 message: None,
294 }];
295
296 let result = inherit_validation_rules(&parent, &child, InheritanceMode::ChildFirst);
297 assert_eq!(result.len(), 2);
298 assert!(matches!(result[0], ValidationRule::Pattern { .. }));
299 assert!(matches!(result[1], ValidationRule::Required));
300 }
301
302 #[test]
303 fn test_parent_first_mode() {
304 let parent = vec![ValidationRule::Required];
305 let child = vec![ValidationRule::Pattern {
306 pattern: "^[a-z]+$".to_string(),
307 message: None,
308 }];
309
310 let result = inherit_validation_rules(&parent, &child, InheritanceMode::ParentFirst);
311 assert_eq!(result.len(), 2);
312 assert!(matches!(result[0], ValidationRule::Required));
313 assert!(matches!(result[1], ValidationRule::Pattern { .. }));
314 }
315
316 #[test]
317 fn test_registry_register_type() {
318 let mut registry = ValidationRuleRegistry::new();
319 let rules = vec![RuleMetadata::new(ValidationRule::Required, "UserInput")];
320 registry.register_type("UserInput", rules);
321
322 assert!(registry.rules_by_type.contains_key("UserInput"));
323 }
324
325 #[test]
326 fn test_registry_set_parent() {
327 let mut registry = ValidationRuleRegistry::new();
328 registry.set_parent("AdminUserInput", "UserInput");
329
330 assert_eq!(registry.get_parent("AdminUserInput"), Some("UserInput"));
331 }
332
333 #[test]
334 fn test_registry_has_parent() {
335 let mut registry = ValidationRuleRegistry::new();
336 registry.set_parent("ChildType", "ParentType");
337
338 assert!(registry.has_parent("ChildType"));
339 assert!(!registry.has_parent("ParentType"));
340 }
341
342 #[test]
343 fn test_registry_get_rules_with_merge() {
344 let mut registry = ValidationRuleRegistry::new();
345
346 let parent_rules = vec![RuleMetadata::new(ValidationRule::Required, "UserInput")];
347 registry.register_type("UserInput", parent_rules);
348
349 let child_rules = vec![RuleMetadata::new(
350 ValidationRule::Length {
351 min: Some(5),
352 max: None,
353 },
354 "AdminUserInput",
355 )];
356 registry.register_type("AdminUserInput", child_rules);
357 registry.set_parent("AdminUserInput", "UserInput");
358
359 let inherited = registry.get_rules("AdminUserInput", InheritanceMode::Merge);
360 assert_eq!(inherited.len(), 2);
361 }
362
363 #[test]
364 fn test_registry_get_rules_with_override() {
365 let mut registry = ValidationRuleRegistry::new();
366
367 let parent_rules = vec![RuleMetadata::new(ValidationRule::Required, "UserInput")];
368 registry.register_type("UserInput", parent_rules);
369
370 let child_rules = vec![RuleMetadata::new(
371 ValidationRule::Length {
372 min: Some(5),
373 max: None,
374 },
375 "AdminUserInput",
376 )];
377 registry.register_type("AdminUserInput", child_rules);
378 registry.set_parent("AdminUserInput", "UserInput");
379
380 let inherited = registry.get_rules("AdminUserInput", InheritanceMode::Override);
381 assert_eq!(inherited.len(), 1);
382 assert!(matches!(inherited[0].rule, ValidationRule::Length { .. }));
383 }
384
385 #[test]
386 fn test_validate_inheritance_success() {
387 let mut registry = ValidationRuleRegistry::new();
388 let parent_rules = vec![RuleMetadata::new(ValidationRule::Required, "UserInput")];
389 registry.register_type("UserInput", parent_rules);
390
391 let result = validate_inheritance("AdminUserInput", "UserInput", ®istry);
392 assert!(result.is_ok());
393 }
394
395 #[test]
396 fn test_validate_inheritance_parent_not_found() {
397 let registry = ValidationRuleRegistry::new();
398 let result = validate_inheritance("AdminUserInput", "NonExistent", ®istry);
399 assert!(result.is_err());
400 assert!(result.unwrap_err().contains("not found"));
401 }
402
403 #[test]
404 fn test_validate_inheritance_circular() {
405 let mut registry = ValidationRuleRegistry::new();
406
407 let user_rules = vec![RuleMetadata::new(ValidationRule::Required, "UserInput")];
408 registry.register_type("UserInput", user_rules);
409
410 let admin_rules = vec![RuleMetadata::new(
411 ValidationRule::Required,
412 "AdminUserInput",
413 )];
414 registry.register_type("AdminUserInput", admin_rules);
415
416 registry.set_parent("UserInput", "AdminUserInput");
417 registry.set_parent("AdminUserInput", "UserInput");
418
419 let result = validate_inheritance("UserInput", "AdminUserInput", ®istry);
420 assert!(result.is_err());
421 assert!(result.unwrap_err().contains("Circular"));
422 }
423
424 #[test]
425 fn test_multi_level_inheritance() {
426 let mut registry = ValidationRuleRegistry::new();
427
428 let grandparent_rules = vec![RuleMetadata::new(ValidationRule::Required, "BaseInput")];
430 registry.register_type("BaseInput", grandparent_rules);
431
432 let parent_rules = vec![RuleMetadata::new(
434 ValidationRule::Length {
435 min: Some(5),
436 max: None,
437 },
438 "UserInput",
439 )];
440 registry.register_type("UserInput", parent_rules);
441 registry.set_parent("UserInput", "BaseInput");
442
443 let child_rules = vec![RuleMetadata::new(
445 ValidationRule::Pattern {
446 pattern: "^[a-z]+$".to_string(),
447 message: None,
448 },
449 "AdminUserInput",
450 )];
451 registry.register_type("AdminUserInput", child_rules);
452 registry.set_parent("AdminUserInput", "UserInput");
453
454 let inherited = registry.get_rules("AdminUserInput", InheritanceMode::Merge);
455 assert_eq!(inherited.len(), 3);
457 }
458
459 #[test]
460 fn test_rule_metadata_non_overrideable() {
461 let rule = RuleMetadata::new(ValidationRule::Required, "UserInput").non_overrideable();
462 assert!(!rule.overrideable);
463 assert!(!rule.inherited);
464 }
465
466 #[test]
467 fn test_rule_metadata_as_inherited() {
468 let mut rule = RuleMetadata::new(ValidationRule::Required, "UserInput");
469 rule = rule.as_inherited();
470 assert!(rule.inherited);
471 assert!(rule.overrideable);
472 }
473
474 #[test]
475 fn test_inheritance_mode_description() {
476 assert!(!InheritanceMode::Override.description().is_empty());
477 assert!(!InheritanceMode::Merge.description().is_empty());
478 assert!(!InheritanceMode::ChildFirst.description().is_empty());
479 assert!(!InheritanceMode::ParentFirst.description().is_empty());
480 }
481
482 #[test]
483 fn test_complex_inheritance_scenario() {
484 let mut registry = ValidationRuleRegistry::new();
485
486 let base_rules = vec![
488 RuleMetadata::new(ValidationRule::Required, "BaseInput"),
489 RuleMetadata::new(
490 ValidationRule::Length {
491 min: Some(5),
492 max: None,
493 },
494 "BaseInput",
495 ),
496 ];
497 registry.register_type("BaseInput", base_rules);
498
499 let user_rules = vec![RuleMetadata::new(
501 ValidationRule::Pattern {
502 pattern: "^[a-z]+$".to_string(),
503 message: None,
504 },
505 "UserInput",
506 )];
507 registry.register_type("UserInput", user_rules);
508 registry.set_parent("UserInput", "BaseInput");
509
510 let admin_rules = vec![RuleMetadata::new(
512 ValidationRule::Enum {
513 values: vec!["admin".to_string(), "moderator".to_string()],
514 },
515 "AdminUserInput",
516 )];
517 registry.register_type("AdminUserInput", admin_rules);
518 registry.set_parent("AdminUserInput", "UserInput");
519
520 let inherited = registry.get_rules("AdminUserInput", InheritanceMode::Merge);
521 assert_eq!(inherited.len(), 4);
523 }
524
525 #[test]
526 fn test_empty_child_rules() {
527 let parent = vec![ValidationRule::Required];
528 let child: Vec<ValidationRule> = vec![];
529
530 let result = inherit_validation_rules(&parent, &child, InheritanceMode::Merge);
531 assert_eq!(result.len(), 1);
532 }
533
534 #[test]
535 fn test_empty_parent_rules() {
536 let parent: Vec<ValidationRule> = vec![];
537 let child = vec![ValidationRule::Required];
538
539 let result = inherit_validation_rules(&parent, &child, InheritanceMode::Merge);
540 assert_eq!(result.len(), 1);
541 }
542
543 #[test]
544 fn test_empty_both_rules() {
545 let parent: Vec<ValidationRule> = vec![];
546 let child: Vec<ValidationRule> = vec![];
547
548 let result = inherit_validation_rules(&parent, &child, InheritanceMode::Merge);
549 assert!(result.is_empty());
550 }
551}