use oxirs_core::OxirsError;
use serde::{Deserialize, Serialize};
use thiserror::Error;
use tracing::{debug, info, span, Level};
pub mod adaptive_query_optimizer;
pub mod advanced_query;
pub mod annotation_aggregation;
pub mod annotation_lifecycle;
pub mod annotation_paths;
pub mod annotation_profile;
pub mod annotations;
pub mod backup_restore;
pub mod bloom_filter;
pub mod cache;
pub mod cli;
pub mod cluster_scaling;
pub mod compact_annotation_storage;
pub mod compatibility;
pub mod compliance;
pub mod compliance_reporting;
pub mod cryptographic_provenance;
pub mod distributed;
pub mod docs;
pub mod enhanced_errors;
pub mod execution;
pub mod functions;
pub mod governance;
pub mod gpu_acceleration;
pub mod graph_diff;
pub mod graphql_star;
pub mod hdt_star;
pub mod index;
pub mod jit_query_engine;
pub mod kg_embeddings;
pub mod lsm_annotation_store;
pub mod materialized_views;
pub mod memory_efficient_store;
pub mod migration_tools;
pub mod ml_embedding_pipeline;
pub mod ml_sparql_optimizer;
pub mod model;
pub mod monitoring;
pub mod parallel_query;
pub mod parser;
pub mod production;
pub mod profiling;
pub mod property_graph_bridge;
pub mod quantum_sparql_optimizer;
pub mod query;
pub mod query_optimizer;
pub mod quoted_graph;
pub mod rdf_star_formats;
pub mod reasoning;
pub mod reification;
pub mod reification_bridge;
pub mod security_audit;
pub mod semantics;
pub mod serialization;
pub mod serializer;
pub mod shacl_star;
pub mod sparql;
pub mod sparql_enhanced;
pub mod sparql_star_bind_values;
pub mod sparql_star_extended;
pub mod storage;
pub mod storage_integration;
pub mod store;
pub mod streaming_query;
pub mod temporal_versioning;
pub mod testing_utilities;
pub mod tiered_storage;
pub mod troubleshooting;
pub mod trust_scoring;
pub mod validation_framework;
pub mod w3c_compliance;
pub mod reification_mapper;
pub mod write_ahead_log;
pub mod triple_reifier;
pub mod provenance_tracker;
pub mod rdf_patch;
pub mod quoted_triple_store;
pub mod annotation_graph;
pub mod rdf_star_serializer;
pub mod star_pattern_matcher;
pub mod star_normalizer;
pub mod star_query_rewriter;
pub mod triple_diff;
pub mod star_statistics;
pub mod graph_merger;
pub use enhanced_errors::{
EnhancedError, EnhancedResult, ErrorAggregator, ErrorCategory, ErrorContext, ErrorSeverity,
WithErrorContext,
};
pub use model::*;
pub use store::StarStore;
pub use troubleshooting::{DiagnosticAnalyzer, MigrationAssistant, TroubleshootingGuide};
#[derive(Debug, Error)]
#[error("Parse error: {message}")]
pub struct ParseErrorDetails {
pub message: String,
pub line: Option<usize>,
pub column: Option<usize>,
pub input_fragment: Option<String>,
pub expected: Option<String>,
pub suggestion: Option<String>,
}
#[derive(Debug, Error)]
pub enum StarError {
#[error("Invalid quoted triple: {message}")]
InvalidQuotedTriple {
message: String,
context: Option<String>,
suggestion: Option<String>,
},
#[error("Parse error in RDF-star format: {0}")]
ParseError(#[from] Box<ParseErrorDetails>),
#[error("Serialization error: {message}")]
SerializationError {
message: String,
format: Option<String>,
context: Option<String>,
},
#[error("SPARQL-star query error: {message}")]
QueryError {
message: String,
query_fragment: Option<String>,
position: Option<usize>,
suggestion: Option<String>,
},
#[error("Core RDF error: {0}")]
CoreError(#[from] OxirsError),
#[error("Reification error: {message}")]
ReificationError {
message: String,
reification_strategy: Option<String>,
context: Option<String>,
},
#[error("Invalid term type for RDF-star context: {message}")]
InvalidTermType {
message: String,
term_type: Option<String>,
expected_types: Option<Vec<String>>,
suggestion: Option<String>,
},
#[error("Nesting depth exceeded: maximum depth {max_depth} reached")]
NestingDepthExceeded {
max_depth: usize,
current_depth: usize,
context: Option<String>,
},
#[error("Format not supported: {format}")]
UnsupportedFormat {
format: String,
available_formats: Vec<String>,
},
#[error("Configuration error: {message}")]
ConfigurationError {
message: String,
parameter: Option<String>,
valid_range: Option<String>,
},
#[error("Internal error: {message}")]
InternalError {
message: String,
context: Option<String>,
},
}
pub type StarResult<T> = std::result::Result<T, StarError>;
impl StarError {
pub fn invalid_quoted_triple(message: impl Into<String>) -> Self {
Self::InvalidQuotedTriple {
message: message.into(),
context: None,
suggestion: None,
}
}
pub fn parse_error(message: impl Into<String>) -> Self {
Self::ParseError(Box::new(ParseErrorDetails {
message: message.into(),
line: None,
column: None,
input_fragment: None,
expected: None,
suggestion: None,
}))
}
pub fn serialization_error(message: impl Into<String>) -> Self {
Self::SerializationError {
message: message.into(),
format: None,
context: None,
}
}
pub fn query_error(message: impl Into<String>) -> Self {
Self::QueryError {
message: message.into(),
query_fragment: None,
position: None,
suggestion: None,
}
}
pub fn reification_error(message: impl Into<String>) -> Self {
Self::ReificationError {
message: message.into(),
reification_strategy: None,
context: None,
}
}
pub fn invalid_term_type(message: impl Into<String>) -> Self {
Self::InvalidTermType {
message: message.into(),
term_type: None,
expected_types: None,
suggestion: None,
}
}
pub fn nesting_depth_exceeded(
max_depth: usize,
current_depth: usize,
context: Option<String>,
) -> Self {
Self::NestingDepthExceeded {
max_depth,
current_depth,
context,
}
}
pub fn configuration_error(message: impl Into<String>) -> Self {
Self::ConfigurationError {
message: message.into(),
parameter: None,
valid_range: None,
}
}
pub fn internal_error(message: impl Into<String>) -> Self {
Self::InternalError {
message: message.into(),
context: None,
}
}
pub fn lock_error(context: impl Into<String>) -> Self {
Self::InternalError {
message: "Lock poisoned".to_string(),
context: Some(context.into()),
}
}
pub fn unsupported_format(format: impl Into<String>, available: Vec<String>) -> Self {
Self::UnsupportedFormat {
format: format.into(),
available_formats: available,
}
}
pub fn recovery_suggestions(&self) -> Vec<String> {
let mut suggestions = Vec::new();
match self {
Self::NestingDepthExceeded { max_depth, .. } => {
suggestions.push(format!(
"Consider increasing max_nesting_depth beyond {max_depth}"
));
suggestions.push("Check for circular references in quoted triples".to_string());
}
Self::UnsupportedFormat {
available_formats, ..
} => {
suggestions.push(format!(
"Supported formats: {}",
available_formats.join(", ")
));
}
Self::ConfigurationError {
valid_range: Some(range),
..
} => {
suggestions.push(format!("Valid range: {range}"));
}
Self::ConfigurationError {
valid_range: None, ..
} => {}
_ => {}
}
suggestions
}
pub fn resource_error(message: impl Into<String>) -> Self {
Self::ConfigurationError {
message: message.into(),
parameter: Some("resource".to_string()),
valid_range: None,
}
}
pub fn processing_error(message: impl Into<String>) -> Self {
Self::ConfigurationError {
message: message.into(),
parameter: Some("processing".to_string()),
valid_range: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StarConfig {
pub max_nesting_depth: usize,
pub enable_reification_fallback: bool,
pub strict_mode: bool,
pub enable_sparql_star: bool,
pub buffer_size: usize,
pub max_parse_errors: Option<usize>,
}
impl Default for StarConfig {
fn default() -> Self {
Self {
max_nesting_depth: 10,
enable_reification_fallback: true,
strict_mode: false,
enable_sparql_star: true,
buffer_size: 8192,
max_parse_errors: Some(100),
}
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct StarStatistics {
pub quoted_triples_count: usize,
pub max_nesting_encountered: usize,
pub reified_triples_count: usize,
pub sparql_star_queries_count: usize,
pub processing_time_us: u64,
}
pub fn init_star_system(config: StarConfig) -> StarResult<()> {
let span = span!(Level::INFO, "init_star_system");
let _enter = span.enter();
info!("Initializing OxiRS RDF-star system");
debug!("Configuration: {:?}", config);
if config.max_nesting_depth == 0 {
return Err(StarError::ConfigurationError {
message: "Max nesting depth must be greater than 0".to_string(),
parameter: Some("max_nesting_depth".to_string()),
valid_range: Some("1..=1000".to_string()),
});
}
if config.buffer_size == 0 {
return Err(StarError::ConfigurationError {
message: "Buffer size must be greater than 0".to_string(),
parameter: Some("buffer_size".to_string()),
valid_range: Some("1..=1048576".to_string()),
});
}
if config.max_nesting_depth > 1000 {
return Err(StarError::ConfigurationError {
message: "Max nesting depth is too large and may cause performance issues".to_string(),
parameter: Some("max_nesting_depth".to_string()),
valid_range: Some("1..=1000".to_string()),
});
}
info!("RDF-star system initialized successfully");
Ok(())
}
pub fn validate_nesting_depth(term: &StarTerm, max_depth: usize) -> StarResult<()> {
fn check_depth(term: &StarTerm, current_depth: usize, max_depth: usize) -> StarResult<usize> {
match term {
StarTerm::QuotedTriple(triple) => {
if current_depth >= max_depth {
return Err(StarError::InvalidQuotedTriple {
message: format!(
"Nesting depth {current_depth} exceeds maximum {max_depth}"
),
context: None,
suggestion: None,
});
}
let subj_depth = check_depth(&triple.subject, current_depth + 1, max_depth)?;
let pred_depth = check_depth(&triple.predicate, current_depth + 1, max_depth)?;
let obj_depth = check_depth(&triple.object, current_depth + 1, max_depth)?;
Ok(subj_depth.max(pred_depth).max(obj_depth))
}
_ => Ok(current_depth),
}
}
check_depth(term, 0, max_depth)?;
Ok(())
}
pub const VERSION: &str = env!("CARGO_PKG_VERSION");
pub mod dev_tools {
use super::*;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq)]
pub enum DetectedFormat {
TurtleStar,
NTriplesStar,
TrigStar,
NQuadsStar,
Unknown,
}
pub fn detect_format(content: &str) -> DetectedFormat {
let content = content.trim();
if content.contains("GRAPH") || content.contains("{") && content.contains("}") {
return DetectedFormat::TrigStar;
}
let lines: Vec<&str> = content
.lines()
.filter(|line| !line.trim().is_empty() && !line.trim().starts_with('#'))
.collect();
if !lines.is_empty() {
let first_line = lines[0].trim();
let terms: Vec<&str> = first_line.split_whitespace().collect();
if terms.len() >= 4 && first_line.ends_with('.') {
return DetectedFormat::NQuadsStar;
}
}
if content.contains("<<") && content.contains(">>") {
if content.contains("@prefix") || content.contains("PREFIX") {
return DetectedFormat::TurtleStar;
}
return DetectedFormat::NTriplesStar;
}
if content.contains("@prefix") || content.contains("@base") {
return DetectedFormat::TurtleStar;
}
DetectedFormat::Unknown
}
pub fn validate_content(content: &str, config: &StarConfig) -> ValidationResult {
let mut result = ValidationResult::new();
result.detected_format = detect_format(content);
let quoted_count = content.matches("<<").count();
result.quoted_triple_count = quoted_count;
if quoted_count > 10000 && !config.enable_reification_fallback {
result.warnings.push("Large number of quoted triples detected. Consider enabling reification fallback for better performance.".to_string());
}
let max_nesting = find_max_nesting_depth(content);
result.max_nesting_depth = max_nesting;
if max_nesting > config.max_nesting_depth {
result.errors.push(format!(
"Nesting depth {} exceeds configured maximum {}",
max_nesting, config.max_nesting_depth
));
}
check_syntax_issues(content, &mut result);
result
}
#[derive(Debug, Clone)]
pub struct ValidationResult {
pub detected_format: DetectedFormat,
pub quoted_triple_count: usize,
pub max_nesting_depth: usize,
pub errors: Vec<String>,
pub warnings: Vec<String>,
pub suggestions: Vec<String>,
pub line_errors: HashMap<u32, String>,
}
impl ValidationResult {
fn new() -> Self {
Self {
detected_format: DetectedFormat::Unknown,
quoted_triple_count: 0,
max_nesting_depth: 0,
errors: Vec::new(),
warnings: Vec::new(),
suggestions: Vec::new(),
line_errors: HashMap::new(),
}
}
pub fn is_valid(&self) -> bool {
self.errors.is_empty()
}
pub fn summary(&self) -> String {
let mut summary = String::new();
summary.push_str(&format!("Format: {:?}\n", self.detected_format));
summary.push_str(&format!("Quoted triples: {}\n", self.quoted_triple_count));
summary.push_str(&format!("Max nesting depth: {}\n", self.max_nesting_depth));
if !self.errors.is_empty() {
summary.push_str(&format!("Errors: {}\n", self.errors.len()));
}
if !self.warnings.is_empty() {
summary.push_str(&format!("Warnings: {}\n", self.warnings.len()));
}
summary
}
}
fn find_max_nesting_depth(content: &str) -> usize {
let mut max_depth: usize = 0;
let mut current_depth: i32 = 0;
for ch in content.chars() {
match ch {
'<' => {
current_depth += 1;
}
'>' => {
current_depth = current_depth.saturating_sub(1);
}
_ => {}
}
max_depth = max_depth.max((current_depth / 2).max(0) as usize); }
max_depth
}
fn check_syntax_issues(content: &str, result: &mut ValidationResult) {
let lines: Vec<&str> = content.lines().collect();
for (line_num, line) in lines.iter().enumerate() {
let line_num = line_num as u32 + 1;
let trimmed = line.trim();
if trimmed.is_empty() || trimmed.starts_with('#') {
continue;
}
let open_count = trimmed.matches("<<").count();
let close_count = trimmed.matches(">>").count();
if open_count != close_count {
result.line_errors.insert(
line_num,
format!(
"Unmatched quoted triple brackets: {open_count} << vs {close_count} >>"
),
);
}
if (result.detected_format == DetectedFormat::NTriplesStar
|| result.detected_format == DetectedFormat::NQuadsStar)
&& !trimmed.ends_with('.')
&& !trimmed.starts_with('@')
&& !trimmed.starts_with("PREFIX")
{
result.warnings.push(format!(
"Line {line_num}: Missing period at end of statement"
));
}
}
}
pub struct StarProfiler {
start_time: std::time::Instant,
operation_times: HashMap<String, u64>,
}
impl StarProfiler {
pub fn new() -> Self {
Self {
start_time: std::time::Instant::now(),
operation_times: HashMap::new(),
}
}
pub fn time_operation<F, R>(&mut self, name: &str, operation: F) -> R
where
F: FnOnce() -> R,
{
let start = std::time::Instant::now();
let result = operation();
let duration = start.elapsed().as_micros() as u64;
self.operation_times.insert(name.to_string(), duration);
result
}
pub fn get_stats(&self) -> HashMap<String, u64> {
self.operation_times.clone()
}
pub fn total_time(&self) -> u64 {
self.start_time.elapsed().as_micros() as u64
}
}
impl Default for StarProfiler {
fn default() -> Self {
Self::new()
}
}
pub fn generate_diagnostic_report(content: &str, config: &StarConfig) -> String {
let validation = validate_content(content, config);
let mut report = String::new();
report.push_str("=== RDF-star Diagnostic Report ===\n\n");
report.push_str(&validation.summary());
if !validation.errors.is_empty() {
report.push_str("\nErrors:\n");
for (i, error) in validation.errors.iter().enumerate() {
report.push_str(&format!(" {}. {}\n", i + 1, error));
}
}
if !validation.warnings.is_empty() {
report.push_str("\nWarnings:\n");
for (i, warning) in validation.warnings.iter().enumerate() {
report.push_str(&format!(" {}. {}\n", i + 1, warning));
}
}
if !validation.suggestions.is_empty() {
report.push_str("\nSuggestions:\n");
for (i, suggestion) in validation.suggestions.iter().enumerate() {
report.push_str(&format!(" {}. {}\n", i + 1, suggestion));
}
}
if !validation.line_errors.is_empty() {
report.push_str("\nLine-specific issues:\n");
let mut sorted_lines: Vec<_> = validation.line_errors.iter().collect();
sorted_lines.sort_by_key(|(line, _)| *line);
for (line, error) in sorted_lines {
report.push_str(&format!(" Line {line}: {error}\n"));
}
}
report
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_default() {
let config = StarConfig::default();
assert_eq!(config.max_nesting_depth, 10);
assert!(config.enable_reification_fallback);
assert!(!config.strict_mode);
assert!(config.enable_sparql_star);
}
#[test]
fn test_nesting_depth_validation() {
let simple_term = StarTerm::iri("http://example.org/test").unwrap();
assert!(validate_nesting_depth(&simple_term, 5).is_ok());
let inner_triple = StarTriple::new(
StarTerm::iri("http://example.org/s").unwrap(),
StarTerm::iri("http://example.org/p").unwrap(),
StarTerm::iri("http://example.org/o").unwrap(),
);
let nested_term = StarTerm::quoted_triple(inner_triple);
assert!(validate_nesting_depth(&nested_term, 5).is_ok());
assert!(validate_nesting_depth(&nested_term, 0).is_err());
}
}