oxirs-star 0.3.1

RDF-star and SPARQL-star grammar support for quoted triples
Documentation
use clap::{Arg, Command};
use serde;

use crate::parser::StarFormat;

/// Build the CLI application structure
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
        )
    }
}