shacl_validation/helpers/
constraint.rs

1use shacl_ast::compiled::component::CompiledComponent;
2use shacl_ast::compiled::shape::CompiledShape;
3use srdf::Object;
4use srdf::Rdf;
5use srdf::Sparql;
6
7use crate::constraints::constraint_error::ConstraintError;
8use crate::validation_report::result::ValidationResult;
9use crate::value_nodes::IterationStrategy;
10use crate::value_nodes::ValueNodeIteration;
11use crate::value_nodes::ValueNodes;
12
13fn apply<S: Rdf, I: IterationStrategy<S>>(
14    component: &CompiledComponent<S>,
15    shape: &CompiledShape<S>,
16    value_nodes: &ValueNodes<S>,
17    iteration_strategy: I,
18    evaluator: impl Fn(&I::Item) -> Result<bool, ConstraintError>,
19) -> Result<Vec<ValidationResult>, ConstraintError> {
20    let results = iteration_strategy
21        .iterate(value_nodes)
22        .flat_map(|(focus_node, item)| {
23            if let Ok(condition) = evaluator(item) {
24                if condition {
25                    let focus = focus_node.clone().into();
26                    let component = Object::iri(component.into());
27                    let severity = shape.severity().clone().into();
28                    let source = Some(shape.id().clone().into());
29                    return Some(
30                        ValidationResult::new(focus, component, severity).with_source(source),
31                    );
32                }
33            }
34            None
35        })
36        .collect();
37
38    Ok(results)
39}
40
41pub fn validate_with<S: Rdf, I: IterationStrategy<S>>(
42    component: &CompiledComponent<S>,
43    shape: &CompiledShape<S>,
44    value_nodes: &ValueNodes<S>,
45    iteration_strategy: I,
46    evaluator: impl Fn(&I::Item) -> bool,
47) -> Result<Vec<ValidationResult>, ConstraintError> {
48    apply(
49        component,
50        shape,
51        value_nodes,
52        iteration_strategy,
53        |item: &I::Item| Ok(evaluator(item)),
54    )
55}
56
57pub fn validate_ask_with<S: Sparql>(
58    component: &CompiledComponent<S>,
59    shape: &CompiledShape<S>,
60    store: &S,
61    value_nodes: &ValueNodes<S>,
62    eval_query: impl Fn(&S::Term) -> String,
63) -> Result<Vec<ValidationResult>, ConstraintError> {
64    apply(
65        component,
66        shape,
67        value_nodes,
68        ValueNodeIteration,
69        |value_node| match store.query_ask(&eval_query(value_node)) {
70            Ok(ask) => Ok(!ask),
71            Err(err) => Err(ConstraintError::Query(format!("ASK query failed: {}", err))),
72        },
73    )
74}