use std::collections::HashMap;
use sphinx_ultra::validation::{
ConstraintDefinition, ContentItem, FieldValue, ItemLocation, ValidationConfig,
ValidationContext, ValidationSettings, ValidationSeverity,
};
use sphinx_ultra::ConstraintEngine;
fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
println!("Sphinx Ultra - Constraint Validation Example");
println!("============================================");
let mut content_item = create_sample_requirement();
println!("\nCreated content item: {}", content_item.id);
println!("Title: {}", content_item.title);
println!("Status: {:?}", content_item.metadata.get("status"));
println!("Priority: {:?}", content_item.metadata.get("priority"));
let config = create_validation_config();
println!(
"\nCreated validation config with {} constraints",
config.constraints.len()
);
let mut all_items = HashMap::new();
all_items.insert(content_item.id.clone(), content_item.clone());
let mut engine = ConstraintEngine::new();
println!("\nInitialized constraint engine");
println!("\nProcessing constraints...");
{
let context = ValidationContext {
current_item: &content_item,
all_items: &all_items,
config: &config,
variables: HashMap::new(),
};
match engine.process_constraints(&content_item, &context) {
Ok((modified_item, failures)) => {
content_item = modified_item;
if failures.is_empty() {
println!("✅ All constraints passed!");
} else {
println!("❌ Found {} constraint failures:", failures.len());
for failure in &failures {
println!(" - Rule: {}", failure.rule.name);
println!(" Severity: {}", failure.severity);
if let Some(msg) = &failure.result.error_message {
println!(" Message: {}", msg);
}
}
}
}
Err(e) => {
println!("❌ Error processing constraints: {}", e);
}
}
}
println!("\nFinal item state:");
println!(" Style: {:?}", content_item.style);
println!("\n{}", "=".repeat(50));
println!("Testing with compliant requirement...");
let compliant_item = create_compliant_requirement();
{
let context2 = ValidationContext {
current_item: &compliant_item,
all_items: &all_items,
config: &config,
variables: HashMap::new(),
};
match engine.process_constraints(&compliant_item, &context2) {
Ok((_modified_compliant, failures)) => {
if failures.is_empty() {
println!("✅ All constraints passed for compliant item!");
} else {
println!(
"❌ Unexpected failures for compliant item: {}",
failures.len()
);
}
}
Err(e) => {
println!("❌ Error: {}", e);
}
}
}
println!("\nExample completed successfully!");
Ok(())
}
fn create_sample_requirement() -> ContentItem {
let mut metadata = HashMap::new();
metadata.insert("status".to_string(), FieldValue::String("open".to_string()));
metadata.insert(
"priority".to_string(),
FieldValue::String("high".to_string()),
);
metadata.insert(
"type".to_string(),
FieldValue::String("requirement".to_string()),
);
metadata.insert(
"tags".to_string(),
FieldValue::Array(vec![
FieldValue::String("security".to_string()),
FieldValue::String("performance".to_string()),
]),
);
ContentItem {
id: "REQ-001".to_string(),
title: "User Authentication Security".to_string(),
content: "The system shall implement secure user authentication with multi-factor support."
.to_string(),
metadata,
constraints: vec!["status_complete".to_string(), "priority_valid".to_string()],
relationships: HashMap::new(),
location: ItemLocation {
docname: "requirements/security.rst".to_string(),
lineno: Some(15),
source_path: Some("docs/requirements/security.rst".to_string()),
},
style: None,
}
}
fn create_compliant_requirement() -> ContentItem {
let mut metadata = HashMap::new();
metadata.insert(
"status".to_string(),
FieldValue::String("complete".to_string()),
);
metadata.insert(
"priority".to_string(),
FieldValue::String("high".to_string()),
);
metadata.insert(
"type".to_string(),
FieldValue::String("requirement".to_string()),
);
ContentItem {
id: "REQ-002".to_string(),
title: "Data Encryption".to_string(),
content: "All sensitive data shall be encrypted at rest and in transit.".to_string(),
metadata,
constraints: vec!["status_complete".to_string(), "priority_valid".to_string()],
relationships: HashMap::new(),
location: ItemLocation {
docname: "requirements/security.rst".to_string(),
lineno: Some(25),
source_path: Some("docs/requirements/security.rst".to_string()),
},
style: None,
}
}
fn create_validation_config() -> ValidationConfig {
let mut constraints = HashMap::new();
constraints.insert(
"status_complete".to_string(),
ConstraintDefinition {
checks: {
let mut checks = HashMap::new();
checks.insert(
"check_0".to_string(),
"priority != 'critical' or status == 'complete'".to_string(),
);
checks.insert(
"check_1".to_string(),
"priority != 'high' or status == 'complete' or status == 'verified'".to_string(),
);
checks
},
severity: ValidationSeverity::Error,
error_message: Some("High/critical priority item {{id}} '{{title}}' must be complete (current status: {{status}})".to_string()),
description: Some("Ensures high and critical priority items are completed".to_string()),
},
);
constraints.insert(
"priority_valid".to_string(),
ConstraintDefinition {
checks: {
let mut checks = HashMap::new();
checks.insert(
"check_0".to_string(),
"priority in ['low', 'medium', 'high', 'critical']".to_string(),
);
checks
},
severity: ValidationSeverity::Warning,
error_message: Some("Item {{id}} has invalid priority '{{priority}}' - must be one of: low, medium, high, critical".to_string()),
description: Some("Validates that priority field contains valid values".to_string()),
},
);
ValidationConfig {
constraints,
constraint_failed_options: ValidationConfig::default().constraint_failed_options,
settings: ValidationSettings {
enable_constraints: true,
cache_results: true,
max_errors: Some(10),
continue_on_error: true,
},
}
}