shacl_validation/constraints/core/value/
node_kind.rs1use 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}