shacl_validation/constraints/core/string_based/
max_length.rs1use crate::constraints::constraint_error::ConstraintError;
2use crate::constraints::NativeValidator;
3use crate::constraints::SparqlValidator;
4use crate::helpers::constraint::validate_ask_with;
5use crate::helpers::constraint::validate_with;
6use crate::validation_report::result::ValidationResult;
7use crate::value_nodes::ValueNodeIteration;
8use crate::value_nodes::ValueNodes;
9use indoc::formatdoc;
10use shacl_ast::compiled::component::CompiledComponent;
11use shacl_ast::compiled::component::MaxLength;
12use shacl_ast::compiled::shape::CompiledShape;
13use srdf::Iri as _;
14use srdf::Literal as _;
15use srdf::Query;
16use srdf::Sparql;
17use srdf::Term;
18use std::fmt::Debug;
19
20impl<S: Query + Debug + 'static> NativeValidator<S> for MaxLength {
21 fn validate_native<'a>(
22 &self,
23 component: &CompiledComponent<S>,
24 shape: &CompiledShape<S>,
25 _: &S,
26 value_nodes: &ValueNodes<S>,
27 _source_shape: Option<&CompiledShape<S>>,
28 ) -> Result<Vec<ValidationResult>, ConstraintError> {
29 let max_length = |value_node: &S::Term| {
30 if value_node.is_blank_node() {
31 true
32 } else if value_node.is_iri() {
33 let iri: S::IRI = match value_node.clone().try_into() {
34 Ok(iri) => iri,
35 Err(_) => todo!(),
36 };
37 iri.as_str().len() > self.max_length() as usize
38 } else if value_node.is_literal() {
39 let literal: S::Literal = match value_node.clone().try_into() {
40 Ok(literal) => literal,
41 Err(_) => todo!(),
42 };
43 literal.lexical_form().len() > self.max_length() as usize
44 } else {
45 todo!()
46 }
47 };
48
49 validate_with(
50 component,
51 shape,
52 value_nodes,
53 ValueNodeIteration,
54 max_length,
55 )
56 }
57}
58
59impl<S: Sparql + Debug + 'static> SparqlValidator<S> for MaxLength {
60 fn validate_sparql(
61 &self,
62 component: &CompiledComponent<S>,
63 shape: &CompiledShape<S>,
64 store: &S,
65 value_nodes: &ValueNodes<S>,
66 _source_shape: Option<&CompiledShape<S>>,
67 ) -> Result<Vec<ValidationResult>, ConstraintError> {
68 let max_length_value = self.max_length();
69
70 let query = |value_node: &S::Term| {
71 formatdoc! {
72 " ASK {{ FILTER (STRLEN(str({})) <= {}) }} ",
73 value_node, max_length_value
74 }
75 };
76
77 validate_ask_with(component, shape, store, value_nodes, query)
78 }
79}