shacl_validation/engine/
native.rs

1use shacl_ast::compiled::component::CompiledComponent;
2use shacl_ast::compiled::property_shape::CompiledPropertyShape;
3use shacl_ast::compiled::shape::CompiledShape;
4use srdf::matcher::Any;
5use srdf::Query;
6use srdf::SHACLPath;
7use srdf::Term;
8use srdf::Triple;
9use srdf::RDFS_SUBCLASS_OF;
10use srdf::RDF_TYPE;
11
12use super::Engine;
13use crate::constraints::NativeDeref;
14use crate::focus_nodes::FocusNodes;
15use crate::helpers::srdf::get_objects_for;
16use crate::helpers::srdf::get_subjects_for;
17use crate::validate_error::ValidateError;
18use crate::validation_report::result::ValidationResult;
19use crate::value_nodes::ValueNodes;
20use std::fmt::Debug;
21
22pub struct NativeEngine;
23
24impl<S: Query + Debug + 'static> Engine<S> for NativeEngine {
25    fn evaluate(
26        &self,
27        store: &S,
28        shape: &CompiledShape<S>,
29        component: &CompiledComponent<S>,
30        value_nodes: &ValueNodes<S>,
31        source_shape: Option<&CompiledShape<S>>,
32    ) -> Result<Vec<ValidationResult>, ValidateError> {
33        println!("NativeEngine, evaluate with shape {}", shape.id());
34        let validator = component.deref();
35        Ok(validator.validate_native(component, shape, store, value_nodes, source_shape)?)
36    }
37
38    /// If s is a shape in a shapes graph SG and s has value t for sh:targetNode
39    /// in SG then { t } is a target from any data graph for s in SG.
40    fn target_node(&self, _: &S, node: &S::Term) -> Result<FocusNodes<S>, ValidateError> {
41        if node.is_blank_node() {
42            Err(ValidateError::TargetNodeBlankNode)
43        } else {
44            Ok(FocusNodes::new(std::iter::once(node.clone())))
45        }
46    }
47
48    fn target_class(&self, store: &S, class: &S::Term) -> Result<FocusNodes<S>, ValidateError> {
49        if !class.is_iri() {
50            return Err(ValidateError::TargetClassNotIri);
51        }
52
53        // TODO: this should not be necessary, check in others triples_matching calls
54        let rdf_type: S::IRI = RDF_TYPE.clone().into();
55
56        let focus_nodes = store
57            .triples_matching(Any, rdf_type, class.clone())
58            .map_err(|_| ValidateError::SRDF)?
59            .map(Triple::into_subject)
60            .map(Into::into);
61
62        Ok(FocusNodes::new(focus_nodes))
63    }
64
65    fn target_subject_of(
66        &self,
67        store: &S,
68        predicate: &S::IRI,
69    ) -> Result<FocusNodes<S>, ValidateError> {
70        let subjects = store
71            .triples_with_predicate(predicate.clone())
72            .map_err(|_| ValidateError::SRDF)?
73            .map(Triple::into_subject)
74            .map(Into::into);
75        let focus_nodes = FocusNodes::new(subjects);
76        Ok(focus_nodes)
77    }
78
79    fn target_object_of(
80        &self,
81        store: &S,
82        predicate: &S::IRI,
83    ) -> Result<FocusNodes<S>, ValidateError> {
84        let objects = store
85            .triples_with_predicate(predicate.clone())
86            .map_err(|_| ValidateError::SRDF)?
87            .map(Triple::into_object);
88        Ok(FocusNodes::new(objects))
89    }
90
91    fn implicit_target_class(
92        &self,
93        store: &S,
94        subject: &S::Term,
95    ) -> Result<FocusNodes<S>, ValidateError> {
96        let targets = get_subjects_for(store, &RDF_TYPE.clone().into(), subject)?;
97
98        let subclass_targets = get_subjects_for(store, &RDFS_SUBCLASS_OF.clone().into(), subject)?
99            .into_iter()
100            .flat_map(move |subclass| {
101                get_subjects_for(store, &RDF_TYPE.clone().into(), &subclass)
102                    .into_iter()
103                    .flatten()
104            });
105
106        Ok(FocusNodes::new(targets.into_iter().chain(subclass_targets)))
107    }
108
109    fn predicate(
110        &self,
111        store: &S,
112        _: &CompiledPropertyShape<S>,
113        predicate: &S::IRI,
114        focus_node: &S::Term,
115    ) -> Result<FocusNodes<S>, ValidateError> {
116        Ok(FocusNodes::new(
117            get_objects_for(store, focus_node, predicate)?.into_iter(),
118        ))
119    }
120
121    fn alternative(
122        &self,
123        _store: &S,
124        _shape: &CompiledPropertyShape<S>,
125        _paths: &[SHACLPath],
126        _focus_node: &S::Term,
127    ) -> Result<FocusNodes<S>, ValidateError> {
128        Err(ValidateError::NotImplemented {
129            msg: "alternative".to_string(),
130        })
131    }
132
133    fn sequence(
134        &self,
135        _store: &S,
136        _shape: &CompiledPropertyShape<S>,
137        _paths: &[SHACLPath],
138        _focus_node: &S::Term,
139    ) -> Result<FocusNodes<S>, ValidateError> {
140        Err(ValidateError::NotImplemented {
141            msg: "sequence".to_string(),
142        })
143    }
144
145    fn inverse(
146        &self,
147        _store: &S,
148        _shape: &CompiledPropertyShape<S>,
149        _path: &SHACLPath,
150        _focus_node: &S::Term,
151    ) -> Result<FocusNodes<S>, ValidateError> {
152        Err(ValidateError::NotImplemented {
153            msg: "inverse".to_string(),
154        })
155    }
156
157    fn zero_or_more(
158        &self,
159        _store: &S,
160        _shape: &CompiledPropertyShape<S>,
161        _path: &SHACLPath,
162        _focus_node: &S::Term,
163    ) -> Result<FocusNodes<S>, ValidateError> {
164        Err(ValidateError::NotImplemented {
165            msg: "zero_or_more".to_string(),
166        })
167    }
168
169    fn one_or_more(
170        &self,
171        _store: &S,
172        _shape: &CompiledPropertyShape<S>,
173        _path: &SHACLPath,
174        _focus_node: &S::Term,
175    ) -> Result<FocusNodes<S>, ValidateError> {
176        Err(ValidateError::NotImplemented {
177            msg: "one_or_more".to_string(),
178        })
179    }
180
181    fn zero_or_one(
182        &self,
183        _store: &S,
184        _shape: &CompiledPropertyShape<S>,
185        _path: &SHACLPath,
186        _focus_node: &S::Term,
187    ) -> Result<FocusNodes<S>, ValidateError> {
188        Err(ValidateError::NotImplemented {
189            msg: "zero_or_one".to_string(),
190        })
191    }
192}