shacl_validation/constraints/core/logical/
xone.rs

1use shacl_ast::compiled::component::CompiledComponent;
2use shacl_ast::compiled::component::Xone;
3use shacl_ast::compiled::shape::CompiledShape;
4use srdf::Query;
5use srdf::Rdf;
6use srdf::Sparql;
7use std::fmt::Debug;
8
9use crate::constraints::constraint_error::ConstraintError;
10use crate::constraints::NativeValidator;
11use crate::constraints::SparqlValidator;
12use crate::constraints::Validator;
13use crate::engine::native::NativeEngine;
14use crate::engine::sparql::SparqlEngine;
15use crate::engine::Engine;
16use crate::focus_nodes::FocusNodes;
17use crate::helpers::constraint::validate_with;
18use crate::shape::Validate;
19use crate::validation_report::result::ValidationResult;
20use crate::value_nodes::ValueNodeIteration;
21use crate::value_nodes::ValueNodes;
22
23impl<S: Rdf + Debug> Validator<S> for Xone<S> {
24    fn validate(
25        &self,
26        component: &CompiledComponent<S>,
27        shape: &CompiledShape<S>,
28        store: &S,
29        engine: impl Engine<S>,
30        value_nodes: &ValueNodes<S>,
31        _source_shape: Option<&CompiledShape<S>>,
32    ) -> Result<Vec<ValidationResult>, ConstraintError> {
33        let xone = |value_node: &S::Term| {
34            self.shapes()
35                .iter()
36                .filter(|shape| {
37                    let focus_nodes = FocusNodes::new(std::iter::once(value_node.clone()));
38                    match shape.validate(store, &engine, Some(&focus_nodes), Some(shape)) {
39                        Ok(results) => results.is_empty(),
40                        Err(_) => false,
41                    }
42                })
43                .count()
44                .ne(&1usize)
45        };
46
47        validate_with(component, shape, value_nodes, ValueNodeIteration, xone)
48    }
49}
50
51impl<S: Query + Debug + 'static> NativeValidator<S> for Xone<S> {
52    fn validate_native(
53        &self,
54        component: &CompiledComponent<S>,
55        shape: &CompiledShape<S>,
56        store: &S,
57        value_nodes: &ValueNodes<S>,
58        source_shape: Option<&CompiledShape<S>>,
59    ) -> Result<Vec<ValidationResult>, ConstraintError> {
60        self.validate(
61            component,
62            shape,
63            store,
64            NativeEngine,
65            value_nodes,
66            source_shape,
67        )
68    }
69}
70
71impl<S: Sparql + Debug + 'static> SparqlValidator<S> for Xone<S> {
72    fn validate_sparql(
73        &self,
74        component: &CompiledComponent<S>,
75        shape: &CompiledShape<S>,
76        store: &S,
77        value_nodes: &ValueNodes<S>,
78        source_shape: Option<&CompiledShape<S>>,
79    ) -> Result<Vec<ValidationResult>, ConstraintError> {
80        self.validate(
81            component,
82            shape,
83            store,
84            SparqlEngine,
85            value_nodes,
86            source_shape,
87        )
88    }
89}