shacl_validation/validation_report/
result.rs1use super::validation_report_error::{ReportError, ResultError};
2use crate::helpers::srdf::get_object_for;
3use shacl_ast::*;
4use srdf::{Object, Query, RDFNode, SRDFBuilder};
5use std::fmt::Debug;
6
7#[derive(Debug, Clone, PartialEq)]
8pub struct ValidationResult {
9 focus_node: RDFNode, path: Option<RDFNode>, value: Option<RDFNode>, source: Option<RDFNode>, constraint_component: RDFNode, details: Option<Vec<RDFNode>>, message: Option<RDFNode>, severity: RDFNode, }
18
19impl ValidationResult {
20 pub fn new(focus_node: Object, constraint_component: Object, severity: Object) -> Self {
22 Self {
23 focus_node,
24 path: None,
25 value: None,
26 source: None,
27 constraint_component,
28 details: None,
29 message: None,
30 severity,
31 }
32 }
33
34 pub fn with_path(mut self, path: Option<Object>) -> Self {
35 self.path = path;
36 self
37 }
38
39 pub fn with_value(mut self, value: Option<Object>) -> Self {
40 self.value = value;
41 self
42 }
43
44 pub fn with_source(mut self, source: Option<Object>) -> Self {
45 self.source = source;
46 self
47 }
48
49 pub fn with_details(mut self, details: Option<Vec<Object>>) -> Self {
50 self.details = details;
51 self
52 }
53
54 pub fn with_message(mut self, message: Option<Object>) -> Self {
55 self.message = message;
56 self
57 }
58
59 pub fn source(&self) -> Option<&Object> {
60 self.source.as_ref()
61 }
62
63 pub fn value(&self) -> Option<&Object> {
64 self.value.as_ref()
65 }
66
67 pub fn focus_node(&self) -> &Object {
68 &self.focus_node
69 }
70
71 pub fn component(&self) -> &Object {
72 &self.constraint_component
73 }
74
75 pub fn severity(&self) -> &Object {
76 &self.severity
77 }
78}
79
80impl ValidationResult {
81 pub(crate) fn parse<S: Query>(
82 store: &S,
83 validation_result: &S::Term,
84 ) -> Result<Self, ResultError> {
85 let focus_node =
88 match get_object_for(store, validation_result, &SH_FOCUS_NODE.clone().into())? {
89 Some(focus_node) => focus_node,
90 None => return Err(ResultError::MissingRequiredField("FocusNode".to_owned())),
91 };
92 let severity =
93 match get_object_for(store, validation_result, &SH_RESULT_SEVERITY.clone().into())? {
94 Some(severity) => severity,
95 None => return Err(ResultError::MissingRequiredField("Severity".to_owned())),
96 };
97 let constraint_component = match get_object_for(
98 store,
99 validation_result,
100 &SH_SOURCE_CONSTRAINT_COMPONENT.clone().into(),
101 )? {
102 Some(constraint_component) => constraint_component,
103 None => {
104 return Err(ResultError::MissingRequiredField(
105 "SourceConstraintComponent".to_owned(),
106 ))
107 }
108 };
109
110 let path = get_object_for(store, validation_result, &SH_RESULT_PATH.clone().into())?;
112 let source = get_object_for(store, validation_result, &SH_SOURCE_SHAPE.clone().into())?;
113 let value = get_object_for(store, validation_result, &SH_VALUE.clone().into())?;
114
115 Ok(
117 ValidationResult::new(focus_node, constraint_component, severity)
118 .with_path(path)
119 .with_source(source)
120 .with_value(value),
121 )
122 }
123
124 pub fn to_rdf<RDF>(
125 &self,
126 rdf_writer: &mut RDF,
127 report_node: RDF::Subject,
128 ) -> Result<(), ReportError>
129 where
130 RDF: SRDFBuilder + Sized,
131 {
132 rdf_writer
133 .add_type(report_node.clone(), SH_VALIDATION_RESULT.clone())
134 .map_err(|e| ReportError::ValidationReportError { msg: e.to_string() })?;
135 rdf_writer
136 .add_triple(
137 report_node.clone(),
138 SH_FOCUS_NODE.clone(),
139 self.focus_node.clone(),
140 )
141 .map_err(|e| ReportError::ValidationReportError {
142 msg: format!("Error adding focus node to validation result: {e}"),
143 })?;
144 rdf_writer
145 .add_triple(
146 report_node.clone(),
147 SH_SOURCE_CONSTRAINT_COMPONENT.clone(),
148 self.constraint_component.clone(),
149 )
150 .map_err(|e| ReportError::ValidationReportError {
151 msg: format!("Error adding source constraint component to validation result: {e}"),
152 })?;
153 rdf_writer
154 .add_triple(
155 report_node.clone(),
156 SH_RESULT_SEVERITY.clone(),
157 self.severity.clone(),
158 )
159 .map_err(|e| ReportError::ValidationReportError {
160 msg: format!("Error adding severity to validation result: {e}"),
161 })?;
162 let message = match self.message {
163 Some(ref message) => message.clone(),
164 None => Object::str("No message"),
165 };
166 rdf_writer
167 .add_triple(report_node.clone(), SH_RESULT_MESSAGE.clone(), message)
168 .map_err(|e| ReportError::ValidationReportError {
169 msg: format!("Error result message to validation result: {e}"),
170 })?;
171 if let Some(source) = &self.source {
172 let source_term: RDF::Term = source.clone().into();
173 rdf_writer
174 .add_triple(report_node.clone(), SH_SOURCE_SHAPE.clone(), source_term)
175 .map_err(|e| ReportError::ValidationReportError {
176 msg: format!("Error adding source to validation result: {e}"),
177 })?;
178 }
179
180 Ok(())
181 }
182}