shacl_validation/constraints/core/value/
node_kind.rs

1use std::ops::Not;
2
3use crate::constraints::constraint_error::ConstraintError;
4use crate::constraints::NativeValidator;
5use crate::constraints::SparqlValidator;
6use crate::helpers::constraint::validate_ask_with;
7use crate::helpers::constraint::validate_with;
8use crate::validation_report::result::ValidationResult;
9use crate::value_nodes::ValueNodeIteration;
10use crate::value_nodes::ValueNodes;
11use indoc::formatdoc;
12use shacl_ast::compiled::component::CompiledComponent;
13use shacl_ast::compiled::component::Nodekind;
14use shacl_ast::compiled::shape::CompiledShape;
15use shacl_ast::node_kind::NodeKind;
16use srdf::Query;
17use srdf::Sparql;
18use srdf::Term;
19use std::fmt::Debug;
20
21impl<S: Query + Debug + 'static> NativeValidator<S> for Nodekind {
22    fn validate_native(
23        &self,
24        component: &CompiledComponent<S>,
25        shape: &CompiledShape<S>,
26        _: &S,
27        value_nodes: &ValueNodes<S>,
28        _source_shape: Option<&CompiledShape<S>>,
29    ) -> Result<Vec<ValidationResult>, ConstraintError> {
30        let node_kind = |value_node: &S::Term| {
31            match (
32                value_node.is_blank_node(),
33                value_node.is_iri(),
34                value_node.is_literal(),
35            ) {
36                (true, false, false) => matches!(
37                    self.node_kind(),
38                    NodeKind::BlankNode | NodeKind::BlankNodeOrIri | NodeKind::BlankNodeOrLiteral
39                ),
40                (false, true, false) => matches!(
41                    self.node_kind(),
42                    NodeKind::Iri | NodeKind::IRIOrLiteral | NodeKind::BlankNodeOrIri
43                ),
44                (false, false, true) => matches!(
45                    self.node_kind(),
46                    NodeKind::Literal | NodeKind::IRIOrLiteral | NodeKind::BlankNodeOrLiteral
47                ),
48                _ => false,
49            }
50            .not()
51        };
52
53        validate_with(component, shape, value_nodes, ValueNodeIteration, node_kind)
54    }
55}
56
57impl<S: Sparql + Debug + 'static> SparqlValidator<S> for Nodekind {
58    fn validate_sparql(
59        &self,
60        component: &CompiledComponent<S>,
61        shape: &CompiledShape<S>,
62        store: &S,
63        value_nodes: &ValueNodes<S>,
64        _source_shape: Option<&CompiledShape<S>>,
65    ) -> Result<Vec<ValidationResult>, ConstraintError> {
66        let node_kind = self.node_kind().clone();
67
68        let query = move |value_node: &S::Term| {
69            if value_node.is_iri() {
70                formatdoc! {"
71                        PREFIX sh: <http://www.w3.org/ns/shacl#>
72                        ASK {{ FILTER ({} IN ( sh:IRI, sh:BlankNodeOrIRI, sh:IRIOrLiteral ) ) }}
73                    ",node_kind
74                }
75            } else if value_node.is_blank_node() {
76                formatdoc! {"
77                        PREFIX sh: <http://www.w3.org/ns/shacl#>
78                        ASK {{ FILTER ({} IN ( sh:Literal, sh:BlankNodeOrLiteral, sh:IRIOrLiteral ) ) }}
79                    ", node_kind
80                }
81            } else {
82                formatdoc! {"
83                        PREFIX sh: <http://www.w3.org/ns/shacl#>
84                        ASK {{ FILTER ({} IN ( sh:BlankNode, sh:BlankNodeOrIRI, sh:BlankNodeOrLiteral ) ) }}
85                    ", node_kind
86                }
87            }
88        };
89
90        validate_ask_with(component, shape, store, value_nodes, query)
91    }
92}