shacl_validation/
shape.rs1use crate::engine::Engine;
2use crate::focus_nodes::FocusNodes;
3use crate::validate_error::ValidateError;
4use crate::validation_report::result::ValidationResult;
5use crate::value_nodes::ValueNodes;
6use shacl_ast::compiled::node_shape::CompiledNodeShape;
7use shacl_ast::compiled::property_shape::CompiledPropertyShape;
8use shacl_ast::compiled::shape::CompiledShape;
9use srdf::Rdf;
10use std::fmt::Debug;
11
12pub trait Validate<S: Rdf> {
14 fn validate(
15 &self,
16 store: &S,
17 runner: &dyn Engine<S>,
18 targets: Option<&FocusNodes<S>>,
19 source_shape: Option<&CompiledShape<S>>,
20 ) -> Result<Vec<ValidationResult>, ValidateError>;
21}
22
23impl<S: Rdf + Debug> Validate<S> for CompiledShape<S> {
24 fn validate(
25 &self,
26 store: &S,
27 runner: &dyn Engine<S>,
28 targets: Option<&FocusNodes<S>>,
29 source_shape: Option<&CompiledShape<S>>,
30 ) -> Result<Vec<ValidationResult>, ValidateError> {
31 println!(
32 "Shape.validate with shape {} and source shape: {}",
33 self.id(),
34 source_shape
35 .map(|s| format!("{}", s.id()))
36 .unwrap_or_else(|| "None".to_string())
37 );
38 if *self.is_deactivated() {
40 return Ok(Vec::default());
41 }
42
43 let focus_nodes = match targets {
45 Some(targets) => targets.to_owned(),
46 None => self.focus_nodes(store, runner),
47 };
48
49 let value_nodes = self.value_nodes(store, &focus_nodes, runner);
53
54 let component_validation_results = self.components().iter().flat_map(move |component| {
56 runner.evaluate(store, self, component, &value_nodes, source_shape)
57 });
58
59 let property_shapes_validation_results =
65 self.property_shapes().iter().flat_map(|prop_shape| {
66 prop_shape.validate(store, runner, Some(&focus_nodes), Some(self))
67 });
68
69 let validation_results = component_validation_results
71 .chain(property_shapes_validation_results)
72 .flatten()
73 .collect();
74
75 Ok(validation_results)
76 }
77}
78
79pub trait FocusNodesOps<S: Rdf> {
80 fn focus_nodes(&self, store: &S, runner: &dyn Engine<S>) -> FocusNodes<S>;
81}
82
83impl<S: Rdf> FocusNodesOps<S> for CompiledShape<S> {
84 fn focus_nodes(&self, store: &S, runner: &dyn Engine<S>) -> FocusNodes<S> {
85 runner
86 .focus_nodes(store, self.targets())
87 .expect("Failed to retrieve focus nodes")
88 }
89}
90
91pub trait ValueNodesOps<S: Rdf> {
92 fn value_nodes(
93 &self,
94 store: &S,
95 focus_nodes: &FocusNodes<S>,
96 runner: &dyn Engine<S>,
97 ) -> ValueNodes<S>;
98}
99
100impl<S: Rdf> ValueNodesOps<S> for CompiledShape<S> {
101 fn value_nodes(
102 &self,
103 store: &S,
104 focus_nodes: &FocusNodes<S>,
105 runner: &dyn Engine<S>,
106 ) -> ValueNodes<S> {
107 match self {
108 CompiledShape::NodeShape(ns) => ns.value_nodes(store, focus_nodes, runner),
109 CompiledShape::PropertyShape(ps) => ps.value_nodes(store, focus_nodes, runner),
110 }
111 }
112}
113
114impl<S: Rdf> ValueNodesOps<S> for CompiledNodeShape<S> {
115 fn value_nodes(&self, _: &S, focus_nodes: &FocusNodes<S>, _: &dyn Engine<S>) -> ValueNodes<S> {
116 let value_nodes = focus_nodes.iter().map(|focus_node| {
117 (
118 focus_node.clone(),
119 FocusNodes::new(std::iter::once(focus_node.clone())),
120 )
121 });
122 ValueNodes::new(value_nodes)
123 }
124}
125
126impl<S: Rdf> ValueNodesOps<S> for CompiledPropertyShape<S> {
127 fn value_nodes(
128 &self,
129 store: &S,
130 focus_nodes: &FocusNodes<S>,
131 runner: &dyn Engine<S>,
132 ) -> ValueNodes<S> {
133 let value_nodes = focus_nodes.iter().filter_map(|focus_node| {
134 runner
135 .path(store, self, focus_node)
136 .ok()
137 .map(|targets| (focus_node.clone(), targets))
138 });
139 ValueNodes::new(value_nodes)
140 }
141}