shacl_validation/constraints/core/string_based/
unique_lang.rs

1use std::cell::RefCell;
2use std::rc::Rc;
3
4use crate::constraints::constraint_error::ConstraintError;
5use crate::constraints::NativeValidator;
6use crate::constraints::SparqlValidator;
7use crate::constraints::Validator;
8use crate::engine::native::NativeEngine;
9use crate::engine::sparql::SparqlEngine;
10use crate::engine::Engine;
11use crate::helpers::constraint::validate_with;
12use crate::validation_report::result::ValidationResult;
13use crate::value_nodes::ValueNodeIteration;
14use crate::value_nodes::ValueNodes;
15use shacl_ast::compiled::component::CompiledComponent;
16use shacl_ast::compiled::component::UniqueLang;
17use shacl_ast::compiled::shape::CompiledShape;
18use srdf::Query;
19use srdf::Rdf;
20use srdf::Sparql;
21use std::fmt::Debug;
22
23impl<S: Rdf + Debug> Validator<S> for UniqueLang {
24    fn validate(
25        &self,
26        component: &CompiledComponent<S>,
27        shape: &CompiledShape<S>,
28        _: &S,
29        _: impl Engine<S>,
30        value_nodes: &ValueNodes<S>,
31        _source_shape: Option<&CompiledShape<S>>,
32    ) -> Result<Vec<ValidationResult>, ConstraintError> {
33        if !self.unique_lang() {
34            return Ok(Default::default());
35        }
36
37        let langs: Rc<RefCell<Vec<_>>> = Rc::new(RefCell::new(Vec::new()));
38
39        let unique_lang = |value_node: &S::Term| {
40            let tmp: Result<S::Literal, _> = value_node.clone().try_into();
41            if let Ok(lang) = tmp {
42                let lang = lang.clone();
43                let mut langs_borrowed = langs.borrow_mut();
44                match langs_borrowed.contains(&lang) {
45                    true => return true,
46                    false => langs_borrowed.push(lang),
47                }
48            }
49            false
50        };
51
52        validate_with(
53            component,
54            shape,
55            value_nodes,
56            ValueNodeIteration,
57            unique_lang,
58        )
59    }
60}
61
62impl<S: Query + Debug + 'static> NativeValidator<S> for UniqueLang {
63    fn validate_native(
64        &self,
65        component: &CompiledComponent<S>,
66        shape: &CompiledShape<S>,
67        store: &S,
68        value_nodes: &ValueNodes<S>,
69        source_shape: Option<&CompiledShape<S>>,
70    ) -> Result<Vec<ValidationResult>, ConstraintError> {
71        self.validate(
72            component,
73            shape,
74            store,
75            NativeEngine,
76            value_nodes,
77            source_shape,
78        )
79    }
80}
81
82impl<S: Sparql + Debug + 'static> SparqlValidator<S> for UniqueLang {
83    fn validate_sparql(
84        &self,
85        component: &CompiledComponent<S>,
86        shape: &CompiledShape<S>,
87        store: &S,
88        value_nodes: &ValueNodes<S>,
89        source_shape: Option<&CompiledShape<S>>,
90    ) -> Result<Vec<ValidationResult>, ConstraintError> {
91        self.validate(
92            component,
93            shape,
94            store,
95            SparqlEngine,
96            value_nodes,
97            source_shape,
98        )
99    }
100}