#[cfg(feature = "sparql")]
mod endpoint;
mod graph;
#[cfg(feature = "sparql")]
mod rdf_data;
use crate::error::ValidationError;
use crate::ir::IRSchema;
use crate::validator::ShaclConfig;
use crate::validator::ShaclValidationMode;
use crate::validator::engine::{Engine, Validate};
use crate::validator::report::{ValidationOutcome, ValidationReport};
#[cfg(feature = "sparql")]
pub use endpoint::EndpointValidation;
pub use graph::GraphValidation;
use rayon::prelude::*;
#[cfg(feature = "sparql")]
pub use rdf_data::DataValidation;
use rudof_rdf::rdf_core::NeighsRDF;
use std::fmt::Debug;
pub trait ShaclProcessor<S: NeighsRDF + Debug + Send + Sync> {
fn store(&self) -> &S;
fn runner(mode: &ShaclValidationMode, config: &ShaclConfig) -> Box<dyn Engine<S>>;
fn prepare_store(&mut self) -> Result<(), ValidationError> {
Ok(())
}
fn validate(
&mut self,
shapes_graph: &IRSchema,
mode: &ShaclValidationMode,
config: &ShaclConfig,
) -> Result<ValidationReport, ValidationError> {
self.prepare_store()?;
let store = self.store();
let mut master_runner = Self::runner(mode, config);
master_runner.build_indexes(store)?;
let levels = shapes_graph.shapes_with_targets_by_level();
let mut all_outcome = ValidationOutcome::new();
for level in levels {
let mut forked_runners: Vec<Box<dyn Engine<S>>> = level.iter().map(|_| master_runner.fork()).collect();
let level_results: Vec<Result<ValidationOutcome, ValidationError>> = forked_runners
.par_iter_mut()
.zip(level.par_iter())
.map(|(runner, idx)| {
let shape = shapes_graph.get_shape_from_idx_e(idx)?;
shape.validate(store, runner.as_mut(), None, Some(shape), shapes_graph)
})
.collect();
for result in level_results {
all_outcome.extend(result?);
}
}
let mut pm = shapes_graph.prefix_map().clone();
if let Some(store_pm) = store.prefixmap() {
pm.merge(store_pm);
}
let conforms = all_outcome.conforms();
let (violations, evidences) = all_outcome.into_parts();
let mut report = ValidationReport::new().with_conforms(conforms).with_prefixmap(pm);
if config.store_errors() {
report = report.with_results(violations);
}
if config.store_evidences() {
let evidences = if config.evidence_shapes_only() {
evidences.into_iter().filter(|e| e.is_shape_level()).collect()
} else {
evidences
};
report = report.with_evidences(evidences);
}
Ok(report)
}
}