use indoc::formatdoc;
use shacl_ast::compiled::component::CompiledComponent;
use shacl_ast::compiled::property_shape::CompiledPropertyShape;
use shacl_ast::compiled::shape::CompiledShape;
use srdf::QuerySRDF;
use srdf::SHACLPath;
use super::Engine;
use crate::constraints::SparqlDeref;
use crate::focus_nodes::FocusNodes;
use crate::helpers::sparql::select;
use crate::validate_error::ValidateError;
use crate::validation_report::result::ValidationResult;
use crate::value_nodes::ValueNodes;
use std::fmt::Debug;
pub struct SparqlEngine;
impl<S: QuerySRDF + Debug + 'static> Engine<S> for SparqlEngine {
fn evaluate(
&self,
store: &S,
shape: &CompiledShape<S>,
component: &CompiledComponent<S>,
value_nodes: &ValueNodes<S>,
) -> Result<Vec<ValidationResult>, ValidateError> {
let validator = component.deref();
Ok(validator.validate_sparql(component, shape, store, value_nodes)?)
}
fn target_node(&self, store: &S, node: &S::Term) -> Result<FocusNodes<S>, ValidateError> {
if S::term_is_bnode(node) {
return Err(ValidateError::TargetNodeBlankNode);
}
let query = formatdoc! {"
SELECT DISTINCT ?this
WHERE {{
BIND ({} AS ?this)
}}
", node};
select(store, query, "this")?;
Err(ValidateError::NotImplemented {
msg: "target_node".to_string(),
})
}
fn target_class(&self, store: &S, class: &S::Term) -> Result<FocusNodes<S>, ValidateError> {
if !S::term_is_iri(class) {
return Err(ValidateError::TargetClassNotIri);
}
let query = formatdoc! {"
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT DISTINCT ?this
WHERE {{
?this rdf:type/rdfs:subClassOf* {} .
}}
", class};
select(store, query, "this")?;
Err(ValidateError::NotImplemented {
msg: "target_class".to_string(),
})
}
fn target_subject_of(
&self,
store: &S,
predicate: &S::IRI,
) -> Result<FocusNodes<S>, ValidateError> {
let query = formatdoc! {"
SELECT DISTINCT ?this
WHERE {{
?this {} ?any .
}}
", predicate};
select(store, query, "this")?;
Err(ValidateError::NotImplemented {
msg: "target_subject_of".to_string(),
})
}
fn target_object_of(
&self,
store: &S,
predicate: &S::IRI,
) -> Result<FocusNodes<S>, ValidateError> {
let query = formatdoc! {"
SELECT DISTINCT ?this
WHERE {{
?any {} ?this .
}}
", predicate};
select(store, query, "this")?;
Err(ValidateError::NotImplemented {
msg: "target_object_of".to_string(),
})
}
fn implicit_target_class(
&self,
_store: &S,
_shape: &CompiledShape<S>,
) -> Result<FocusNodes<S>, ValidateError> {
Err(ValidateError::NotImplemented {
msg: "implicit_target_class".to_string(),
})
}
fn predicate(
&self,
_store: &S,
_shape: &CompiledPropertyShape<S>,
_predicate: &S::IRI,
_focus_node: &S::Term,
) -> Result<FocusNodes<S>, ValidateError> {
Err(ValidateError::NotImplemented {
msg: "predicate".to_string(),
})
}
fn alternative(
&self,
_store: &S,
_shape: &CompiledPropertyShape<S>,
_paths: &[SHACLPath],
_focus_node: &S::Term,
) -> Result<FocusNodes<S>, ValidateError> {
Err(ValidateError::NotImplemented {
msg: "alternative".to_string(),
})
}
fn sequence(
&self,
_store: &S,
_shape: &CompiledPropertyShape<S>,
_paths: &[SHACLPath],
_focus_node: &S::Term,
) -> Result<FocusNodes<S>, ValidateError> {
Err(ValidateError::NotImplemented {
msg: "sequence".to_string(),
})
}
fn inverse(
&self,
_store: &S,
_shape: &CompiledPropertyShape<S>,
_path: &SHACLPath,
_focus_node: &S::Term,
) -> Result<FocusNodes<S>, ValidateError> {
Err(ValidateError::NotImplemented {
msg: "inverse".to_string(),
})
}
fn zero_or_more(
&self,
_store: &S,
_shape: &CompiledPropertyShape<S>,
_path: &SHACLPath,
_focus_node: &S::Term,
) -> Result<FocusNodes<S>, ValidateError> {
Err(ValidateError::NotImplemented {
msg: "zero_or_more".to_string(),
})
}
fn one_or_more(
&self,
_store: &S,
_shape: &CompiledPropertyShape<S>,
_path: &SHACLPath,
_focus_node: &S::Term,
) -> Result<FocusNodes<S>, ValidateError> {
Err(ValidateError::NotImplemented {
msg: "one_or_more".to_string(),
})
}
fn zero_or_one(
&self,
_store: &S,
_shape: &CompiledPropertyShape<S>,
_path: &SHACLPath,
_focus_node: &S::Term,
) -> Result<FocusNodes<S>, ValidateError> {
Err(ValidateError::NotImplemented {
msg: "zero_or_one".to_string(),
})
}
}