use clap::{Arg, Command};
use serde;
use crate::parser::StarFormat;
pub fn build_cli() -> Command {
Command::new("oxirs-star")
.version("1.0.0")
.about("RDF-star validation, conversion, and debugging tools")
.author("OxiRS Team")
.arg(
Arg::new("verbose")
.short('v')
.long("verbose")
.help("Enable verbose output")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("quiet")
.short('q')
.long("quiet")
.help("Suppress all output except errors")
.action(clap::ArgAction::SetTrue),
)
.subcommand(
Command::new("validate")
.about("Validate RDF-star files")
.arg(
Arg::new("input")
.help("Input file path")
.required(true)
.value_name("FILE"),
)
.arg(
Arg::new("format")
.short('f')
.long("format")
.help("Input format (auto-detect if not specified)")
.value_name("FORMAT"),
)
.arg(
Arg::new("strict")
.long("strict")
.help("Use strict validation mode")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("report")
.short('r')
.long("report")
.help("Output detailed validation report")
.value_name("OUTPUT_FILE"),
),
)
.subcommand(
Command::new("convert")
.about("Convert between RDF-star formats")
.arg(
Arg::new("input")
.help("Input file path")
.required(true)
.value_name("INPUT_FILE"),
)
.arg(
Arg::new("output")
.help("Output file path")
.required(true)
.value_name("OUTPUT_FILE"),
)
.arg(
Arg::new("from")
.long("from")
.help("Input format")
.value_name("FORMAT"),
)
.arg(
Arg::new("to")
.long("to")
.help("Output format")
.required(true)
.value_name("FORMAT"),
)
.arg(
Arg::new("pretty")
.long("pretty")
.help("Enable pretty printing")
.action(clap::ArgAction::SetTrue),
),
)
.subcommand(
Command::new("analyze")
.about("Analyze RDF-star data structure and statistics")
.arg(
Arg::new("input")
.help("Input file path")
.required(true)
.value_name("FILE"),
)
.arg(
Arg::new("output")
.short('o')
.long("output")
.help("Output analysis report to file")
.value_name("OUTPUT_FILE"),
)
.arg(
Arg::new("json")
.long("json")
.help("Output analysis in JSON format")
.action(clap::ArgAction::SetTrue),
),
)
.subcommand(
Command::new("debug")
.about("Debug RDF-star parsing issues")
.arg(
Arg::new("input")
.help("Input file path")
.required(true)
.value_name("FILE"),
)
.arg(
Arg::new("line")
.short('l')
.long("line")
.help("Focus on specific line number")
.value_name("LINE_NUMBER"),
)
.arg(
Arg::new("context")
.short('c')
.long("context")
.help("Number of context lines to show around errors")
.value_name("LINES")
.default_value("3"),
),
)
.subcommand(
Command::new("benchmark")
.about("Benchmark parsing and serialization performance")
.arg(
Arg::new("input")
.help("Input file path")
.required(true)
.value_name("FILE"),
)
.arg(
Arg::new("iterations")
.short('n')
.long("iterations")
.help("Number of benchmark iterations")
.value_name("N")
.default_value("10"),
)
.arg(
Arg::new("warmup")
.long("warmup")
.help("Number of warmup iterations")
.value_name("N")
.default_value("3"),
),
)
.subcommand(
Command::new("query")
.about("Execute SPARQL-star queries")
.arg(
Arg::new("data")
.help("RDF-star data file")
.required(true)
.value_name("DATA_FILE"),
)
.arg(
Arg::new("query")
.help("SPARQL-star query file or inline query")
.required(true)
.value_name("QUERY"),
)
.arg(
Arg::new("format")
.short('f')
.long("format")
.help("Output format for results")
.value_name("FORMAT")
.default_value("table"),
),
)
.subcommand(
Command::new("troubleshoot")
.about("Get troubleshooting help for specific errors")
.arg(
Arg::new("error")
.help("Error message or type to troubleshoot")
.required(true)
.value_name("ERROR"),
)
.arg(
Arg::new("output")
.short('o')
.long("output")
.help("Output troubleshooting report to file")
.value_name("OUTPUT_FILE"),
),
)
.subcommand(
Command::new("migrate")
.about("Migrate data from other RDF stores to RDF-star")
.arg(
Arg::new("source")
.help("Source data file")
.required(true)
.value_name("SOURCE_FILE"),
)
.arg(
Arg::new("output")
.help("Output RDF-star file")
.required(true)
.value_name("OUTPUT_FILE"),
)
.arg(
Arg::new("source-format")
.long("source-format")
.help("Source format (standard-rdf, jena, rdflib, etc.)")
.value_name("FORMAT")
.default_value("standard-rdf"),
)
.arg(
Arg::new("plan")
.long("plan")
.help("Generate migration plan without executing")
.action(clap::ArgAction::SetTrue),
),
)
.subcommand(
Command::new("doctor")
.about("Comprehensive diagnostic analysis of RDF-star data")
.arg(
Arg::new("input")
.help("Input file to diagnose")
.required(true)
.value_name("FILE"),
)
.arg(
Arg::new("report")
.short('r')
.long("report")
.help("Output detailed diagnostic report")
.value_name("REPORT_FILE"),
)
.arg(
Arg::new("fix")
.long("fix")
.help("Attempt to automatically fix issues")
.action(clap::ArgAction::SetTrue),
),
)
.subcommand(
Command::new("profile")
.about("Profile RDF-star operations with advanced analytics")
.arg(
Arg::new("input")
.help("Input file to profile")
.required(true)
.value_name("FILE"),
)
.arg(
Arg::new("operations")
.short('o')
.long("operations")
.help("Operations to profile (parse,serialize,query,all)")
.value_name("OPS")
.default_value("all"),
)
.arg(
Arg::new("iterations")
.short('n')
.long("iterations")
.help("Number of profiling iterations")
.value_name("N")
.default_value("10"),
)
.arg(
Arg::new("output")
.short('r')
.long("report")
.help("Output profiling report to file")
.value_name("REPORT_FILE"),
),
)
.subcommand(
Command::new("profile-report")
.about("Generate comprehensive profiling reports from collected data")
.arg(
Arg::new("data")
.help("Profiling data file (JSON format)")
.required(true)
.value_name("DATA_FILE"),
)
.arg(
Arg::new("output")
.short('o')
.long("output")
.help("Output report file")
.value_name("OUTPUT_FILE"),
)
.arg(
Arg::new("format")
.short('f')
.long("format")
.help("Report format (json,html,text)")
.value_name("FORMAT")
.default_value("text"),
),
)
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct ValidationResult {
pub is_valid: bool,
pub errors: Vec<String>,
pub warnings: Vec<String>,
pub triple_count: usize,
pub quoted_triple_count: usize,
pub format: StarFormat,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct AnalysisResult {
pub format: StarFormat,
pub total_triples: usize,
pub quoted_triples: usize,
pub subjects: std::collections::HashSet<String>,
pub predicates: std::collections::HashSet<String>,
pub objects: std::collections::HashSet<String>,
pub max_nesting_depth: usize,
pub namespaces: std::collections::HashSet<String>,
}
#[derive(Debug)]
pub struct BenchmarkResults {
pub file_size: usize,
pub iterations: usize,
pub parse_times: Vec<std::time::Duration>,
pub serialize_times: Vec<std::time::Duration>,
}
#[derive(Debug)]
pub struct SystemHealth {
pub memory_available: bool,
pub disk_space_sufficient: bool,
pub dependencies_satisfied: bool,
pub configuration_valid: bool,
pub overall_status: String,
}
#[derive(Debug)]
pub struct PerformanceAnalysis {
pub file_size_bytes: u64,
pub estimated_parse_time_ms: f64,
pub memory_requirements_mb: f64,
pub optimization_suggestions: Vec<String>,
}
impl std::fmt::Display for PerformanceAnalysis {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"File Size: {} bytes\nParse Time: {:.2}ms\nMemory: {:.2}MB\nSuggestions: {}",
self.file_size_bytes,
self.estimated_parse_time_ms,
self.memory_requirements_mb,
self.optimization_suggestions.len()
)
}
}
impl std::fmt::Display for SystemHealth {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Overall: {}\nMemory Available: {}\nDisk Space: {}\nDependencies: {}\nConfiguration: {}",
self.overall_status,
self.memory_available,
self.disk_space_sufficient,
self.dependencies_satisfied,
self.configuration_valid
)
}
}