shacl_validation/constraints/core/string_based/
min_length.rs

1use 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::MinLength;
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 MinLength {
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 min_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.min_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.min_length() as usize
44            } else {
45                todo!()
46            }
47        };
48
49        validate_with(
50            component,
51            shape,
52            value_nodes,
53            ValueNodeIteration,
54            min_length,
55        )
56    }
57}
58
59impl<S: Sparql + Debug + 'static> SparqlValidator<S> for MinLength {
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 min_length_value = self.min_length();
69
70        let query = |value_node: &S::Term| {
71            formatdoc! {
72                " ASK {{ FILTER (STRLEN(str({})) >= {}) }} ",
73                value_node, min_length_value
74            }
75        };
76
77        validate_ask_with(component, shape, store, value_nodes, query)
78    }
79}