1use crate::{RudofConfig, RudofError, ShapesGraphSource};
2use iri_s::IriS;
3use shacl_ast::{ShaclParser, ShaclWriter};
4use shacl_validation::shacl_processor::{GraphValidation, ShaclProcessor};
5use shacl_validation::store::graph::Graph;
6
7use shapemap::{NodeSelector, ShapeSelector};
8
9use shapes_converter::ShEx2Uml;
10#[cfg(feature = "dctap")]
11use shapes_converter::Tap2ShEx;
12use shex_ast::ir::schema_ir::SchemaIR;
13use shex_compact::ShExParser;
14use shex_validation::{ResolveMethod, SchemaWithoutImports};
15use srdf::Sparql;
16use srdf::{FocusRDF, SRDFGraph};
17use std::fmt::Debug;
18#[cfg(feature = "dctap")]
19use std::path::Path;
20use std::str::FromStr;
21use std::{io, result};
22
23#[cfg(feature = "dctap")]
25pub use dctap::{DCTAPFormat, DCTap as DCTAP};
26pub use iri_s::iri;
27pub use prefixmap::PrefixMap;
28pub use shacl_ast::ShaclFormat;
29pub use shacl_validation::shacl_processor::ShaclValidationMode;
30pub use shacl_validation::validation_report::report::ValidationReport;
31pub use shapemap::{QueryShapeMap, ResultShapeMap, ShapeMapFormat, ValidationStatus};
32pub use shex_compact::{ShExFormatter, ShapeMapParser, ShapemapFormatter as ShapeMapFormatter};
33pub use shex_validation::Validator as ShExValidator;
34pub use shex_validation::{ShExFormat, ValidatorConfig};
35pub use srdf::{QuerySolution, QuerySolutions, RDFFormat, ReaderMode, SRDFSparql, VarName};
36pub type Result<T> = result::Result<T, RudofError>;
37pub use shacl_ast::ast::Schema as ShaclSchema;
38pub use shapes_converter::UmlGenerationMode;
39pub use shex_ast::Schema as ShExSchema;
40pub use sparql_service::RdfData;
41
42#[derive(Debug)]
44pub struct Rudof {
45 config: RudofConfig,
46 rdf_data: RdfData,
47 shacl_schema: Option<ShaclSchema>, shex_schema: Option<ShExSchema>,
49 shex_schema_ir: Option<SchemaIR>,
50 resolved_shex_schema: Option<SchemaWithoutImports>,
51 shex_validator: Option<ShExValidator>,
52 shapemap: Option<QueryShapeMap>,
53
54 #[cfg(feature = "dctap")]
55 dctap: Option<DCTAP>,
56 shex_results: Option<ResultShapeMap>,
57}
58
59unsafe impl Send for Rudof {}
62
63impl Rudof {
64 pub fn new(config: &RudofConfig) -> Rudof {
65 Rudof {
66 config: config.clone(),
67 shex_schema: None,
68 shex_schema_ir: None,
69 shacl_schema: None,
70 resolved_shex_schema: None,
71 shex_validator: None,
72 rdf_data: RdfData::new(),
73 shapemap: None,
74
75 #[cfg(feature = "dctap")]
76 dctap: None,
77 shex_results: None,
78 }
79 }
80
81 pub fn config(&self) -> &RudofConfig {
82 &self.config
83 }
84
85 pub fn update_config(&mut self, config: &RudofConfig) {
86 self.config = config.clone();
87 }
88
89 pub fn reset_data(&mut self) {
91 self.rdf_data = RdfData::new()
92 }
93
94 #[cfg(feature = "dctap")]
95 pub fn reset_dctap(&mut self) {
97 self.dctap = None
98 }
99
100 pub fn reset_shacl(&mut self) {
102 self.shacl_schema = None
103 }
104
105 pub fn reset_all(&mut self) {
107 self.reset_data();
108 #[cfg(feature = "dctap")]
109 self.reset_dctap();
110 self.reset_shacl();
111 self.reset_shapemap();
112 self.reset_validation_results();
113 self.reset_shex();
114 }
115
116 pub fn get_shacl_from_data(&mut self) -> Result<()> {
118 let schema = shacl_schema_from_data(self.rdf_data.clone())?;
119 self.shacl_schema = Some(schema);
120 Ok(())
121 }
122
123 pub fn get_shacl(&self) -> Option<&ShaclSchema> {
125 self.shacl_schema.as_ref()
126 }
127
128 pub fn get_shex(&self) -> Option<&ShExSchema> {
130 self.shex_schema.as_ref()
131 }
132
133 pub fn get_shex_ir(&self) -> Option<&SchemaIR> {
135 self.shex_schema_ir.as_ref()
136 }
137
138 #[cfg(feature = "dctap")]
140 pub fn get_dctap(&self) -> Option<&DCTAP> {
141 self.dctap.as_ref()
142 }
143
144 pub fn get_shapemap(&self) -> Option<&QueryShapeMap> {
146 self.shapemap.as_ref()
147 }
148
149 #[cfg(feature = "dctap")]
152 pub fn dctap2shex(&mut self) -> Result<()> {
153 if let Some(dctap) = self.get_dctap() {
154 let converter = Tap2ShEx::new(&self.config.tap2shex_config());
155 let shex = converter
156 .convert(dctap)
157 .map_err(|e| RudofError::DCTap2ShEx {
158 error: format!("{e}"),
159 })?;
160 self.shex_schema = Some(shex);
161 Ok(())
162 } else {
163 Err(RudofError::NoDCTAP)
164 }
165 }
166
167 pub fn shex2plant_uml<W: io::Write>(
170 &self,
171 mode: &UmlGenerationMode,
172 writer: &mut W,
173 ) -> Result<()> {
174 if let Some(shex) = &self.shex_schema {
175 let mut converter = ShEx2Uml::new(&self.config.shex2uml_config());
176 converter
177 .convert(shex)
178 .map_err(|e| RudofError::ShEx2PlantUmlError {
179 error: format!("{e}"),
180 })?;
181 converter.as_plantuml(writer, mode).map_err(|e| {
182 RudofError::ShEx2PlantUmlErrorAsPlantUML {
183 error: format!("{e}"),
184 }
185 })?;
186 Ok(())
187 } else {
188 Err(RudofError::ShEx2UmlWithoutShEx)
189 }
190 }
191
192 pub fn serialize_data<W: io::Write>(&self, format: &RDFFormat, writer: &mut W) -> Result<()> {
193 self.rdf_data
194 .serialize(format, writer)
195 .map_err(|e| RudofError::SerializingData {
196 error: format!("{e}"),
197 })
198 }
199
200 pub fn serialize_shapemap<W: io::Write>(
202 &self,
203 format: &ShapeMapFormat,
204 formatter: &ShapeMapFormatter,
205 writer: &mut W,
206 ) -> Result<()> {
207 if let Some(shapemap) = &self.shapemap {
208 match format {
209 ShapeMapFormat::Compact => {
210 formatter.write_shapemap(shapemap, writer).map_err(|e| {
211 RudofError::ErrorFormattingShapeMap {
212 shapemap: format!("{:?}", shapemap.clone()),
213 error: format!("{e}"),
214 }
215 })
216 }
217 ShapeMapFormat::JSON => {
218 serde_json::to_writer_pretty(writer, &shapemap).map_err(|e| {
219 RudofError::ErrorWritingShExJson {
220 schema: format!("{:?}", shapemap.clone()),
221 error: format!("{e}"),
222 }
223 })?;
224 Ok(())
225 }
226 }
227 } else {
228 Err(RudofError::NoShapeMapToSerialize)
229 }
230 }
231
232 pub fn serialize_shex<W: io::Write>(
234 &self,
235 format: &ShExFormat,
236 formatter: &ShExFormatter,
237 writer: &mut W,
238 ) -> Result<()> {
239 if let Some(shex) = &self.shex_schema {
240 match format {
241 ShExFormat::ShExC => {
242 formatter.write_schema(shex, writer).map_err(|e| {
243 RudofError::ErrorFormattingSchema {
244 schema: format!("{:?}", shex.clone()),
245 error: format!("{e}"),
246 }
247 })?;
248 Ok(())
249 }
250 ShExFormat::ShExJ => {
251 serde_json::to_writer_pretty(writer, &shex).map_err(|e| {
252 RudofError::ErrorWritingShExJson {
253 schema: format!("{:?}", shex.clone()),
254 error: format!("{e}"),
255 }
256 })?;
257 Ok(())
258 }
259 ShExFormat::Turtle => Err(RudofError::NotImplemented {
260 msg: format!("ShEx to ShExR for {shex:?}"),
261 }),
262 }
263 } else {
264 Err(RudofError::NoShExSchemaToSerialize)
265 }
266 }
267
268 pub fn run_query_str(&mut self, str: &str) -> Result<QuerySolutions<RdfData>> {
269 self.rdf_data
270 .check_store()
271 .map_err(|e| RudofError::StorageError {
272 error: format!("{e}"),
273 })?;
274 let results = self
275 .rdf_data
276 .query_select(str)
277 .map_err(|e| RudofError::QueryError {
278 str: str.to_string(),
279 error: format!("{e}"),
280 })?;
281 Ok(results)
282 }
283
284 pub fn run_query<R: io::Read>(&mut self, reader: &mut R) -> Result<QuerySolutions<RdfData>> {
285 let mut str = String::new();
286 reader
287 .read_to_string(&mut str)
288 .map_err(|e| RudofError::ReadError {
289 error: format!("{e}"),
290 })?;
291 self.run_query_str(str.as_str())
292 }
293
294 pub fn serialize_shacl<W: io::Write>(
295 &self,
296 format: &ShaclFormat,
297 writer: &mut W,
298 ) -> Result<()> {
299 if let Some(shacl) = &self.shacl_schema {
300 match format {
301 ShaclFormat::Internal => {
302 write!(writer, "{shacl}").map_err(|e| RudofError::SerializingSHACLInternal {
303 error: format!("{e}"),
304 })
305 }
306 _ => {
307 let data_format = shacl_format2rdf_format(format)?;
308 let mut shacl_writer: ShaclWriter<SRDFGraph> = ShaclWriter::new();
309 shacl_writer
310 .write(shacl)
311 .map_err(|e| RudofError::WritingSHACL {
312 shacl: format!("{:?}", shacl.clone()),
313 error: format!("{e}"),
314 })?;
315 shacl_writer.serialize(&data_format, writer).map_err(|e| {
316 RudofError::SerializingSHACL {
317 error: format!("{e}"),
318 shacl: format!("{:?}", shacl.clone()),
319 }
320 })?;
321 Ok(())
322 }
323 }
324 } else {
325 Err(RudofError::NoShaclToSerialize)
326 }
327 }
328
329 pub fn reset_validation_results(&mut self) {
332 self.shex_results = None
337 }
338
339 pub fn reset_shex(&mut self) {
342 self.shex_schema = None;
343 self.shex_validator = None
344 }
345
346 pub fn read_shacl<R: io::Read>(
350 &mut self,
351 reader: R,
352 format: &ShaclFormat,
353 base: Option<&str>,
354 reader_mode: &ReaderMode,
355 ) -> Result<()> {
356 let format = match format {
357 ShaclFormat::Internal => Err(RudofError::InternalSHACLFormatNonReadable),
358 ShaclFormat::Turtle => Ok(RDFFormat::Turtle),
359 ShaclFormat::NTriples => Ok(RDFFormat::NTriples),
360 ShaclFormat::RDFXML => Ok(RDFFormat::RDFXML),
361 ShaclFormat::TriG => Ok(RDFFormat::TriG),
362 ShaclFormat::N3 => Ok(RDFFormat::N3),
363 ShaclFormat::NQuads => Ok(RDFFormat::NQuads),
364 }?;
365
366 let rdf_graph =
367 SRDFGraph::from_reader(reader, &format, base, reader_mode).map_err(|e| {
368 RudofError::ReadError {
369 error: format!("{e}"),
370 }
371 })?;
372 let schema = shacl_schema_from_data(rdf_graph)?;
373 self.shacl_schema = Some(schema);
374 Ok(())
375 }
376
377 #[cfg(feature = "dctap")]
380 pub fn read_dctap<R: std::io::Read>(&mut self, reader: R, format: &DCTAPFormat) -> Result<()> {
381 let dctap = match format {
382 DCTAPFormat::CSV => {
383 let dctap = DCTAP::from_reader(reader, &self.config.tap_config()).map_err(|e| {
384 RudofError::DCTAPReaderCSVReader {
385 error: format!("{e}"),
386 }
387 })?;
388 Ok(dctap)
389 }
390 DCTAPFormat::XLS | DCTAPFormat::XLSB | DCTAPFormat::XLSM | DCTAPFormat::XLSX => {
391 Err(RudofError::DCTAPReadXLSNoPath)
392 }
393 }?;
394 self.dctap = Some(dctap);
395 Ok(())
396 }
397
398 #[cfg(feature = "dctap")]
401 pub fn read_dctap_path<P: AsRef<Path>>(&mut self, path: P, format: &DCTAPFormat) -> Result<()> {
402 let path_name = path.as_ref().display().to_string();
403 let dctap =
404 match format {
405 DCTAPFormat::CSV => {
406 let dctap = DCTAP::from_path(path, &self.config.tap_config()).map_err(|e| {
407 RudofError::DCTAPReaderCSV {
408 path: path_name,
409 error: format!("{e}"),
410 }
411 })?;
412 Ok(dctap)
413 }
414 DCTAPFormat::XLS | DCTAPFormat::XLSB | DCTAPFormat::XLSM | DCTAPFormat::XLSX => {
415 let path_buf = path.as_ref().to_path_buf();
416 let dctap = DCTAP::from_excel(path_buf, None, &self.config.tap_config())
417 .map_err(|e| RudofError::DCTAPReaderPathXLS {
418 path: path_name,
419 error: format!("{e}"),
420 format: format!("{format:?}"),
421 })?;
422 Ok(dctap)
423 }
424 }?;
425 self.dctap = Some(dctap);
426 Ok(())
427 }
428
429 pub fn read_shex<R: io::Read>(
434 &mut self,
435 reader: R,
436 format: &ShExFormat,
437 base: Option<&str>,
438 ) -> Result<()> {
439 let schema_json = match format {
440 ShExFormat::ShExC => {
441 let base = match base {
442 Some(str) => {
443 let iri = IriS::from_str(str).map_err(|e| RudofError::BaseIriError {
444 str: str.to_string(),
445 error: format!("{e}"),
446 })?;
447 Ok(Some(iri))
448 }
449 None => Ok(None),
450 }?;
451 let schema_json = ShExParser::from_reader(reader, base).map_err(|e| {
452 RudofError::ShExCParserError {
453 error: format!("{e}"),
454 }
455 })?;
456 Ok(schema_json)
457 }
458 ShExFormat::ShExJ => {
459 let schema_json =
460 ShExSchema::from_reader(reader).map_err(|e| RudofError::ShExJParserError {
461 error: format!("{e}"),
462 })?;
463 Ok(schema_json)
464 }
465 ShExFormat::Turtle => {
466 todo!()
467 }
476 }?;
477 self.shex_schema = Some(schema_json.clone());
478 let mut schema = SchemaIR::new();
479 schema
480 .from_schema_json(&schema_json)
481 .map_err(|e| RudofError::CompilingSchemaError {
482 error: format!("{e}"),
483 })?;
484 self.shex_schema_ir = Some(schema.clone());
485
486 let validator =
487 ShExValidator::new(schema, &self.config.validator_config()).map_err(|e| {
488 RudofError::ShExValidatorCreationError {
489 error: format!("{e}"),
490 schema: format!("{}", schema_json),
491 }
492 })?;
493 self.shex_validator = Some(validator);
494 Ok(())
495 }
496
497 pub fn validate_shacl(
505 &mut self,
506 mode: &ShaclValidationMode,
507 shapes_graph_source: &ShapesGraphSource,
508 ) -> Result<ValidationReport> {
509 let (compiled_schema, shacl_schema) = match shapes_graph_source {
510 ShapesGraphSource::CurrentSchema if self.shacl_schema.is_some() => {
511 let ast_schema = self.shacl_schema.as_ref().unwrap();
512 let compiled_schema = ast_schema.clone().to_owned().try_into().map_err(|e| {
513 RudofError::SHACLCompilationError {
514 error: format!("{e}"),
515 schema: Box::new(ast_schema.clone()),
516 }
517 })?;
518 Ok((compiled_schema, ast_schema.clone()))
519 }
520 _ => {
521 let ast_schema = shacl_schema_from_data(self.rdf_data.clone())?;
522 let compiled_schema = ast_schema.to_owned().try_into().map_err(|e| {
523 RudofError::SHACLCompilationError {
524 error: format!("{e}"),
525 schema: Box::new(ast_schema.clone()),
526 }
527 })?;
528 Ok((compiled_schema, ast_schema))
529 }
530 }?;
531 let validator = GraphValidation::from_graph(Graph::from_data(self.rdf_data.clone()), *mode);
532 let result = ShaclProcessor::validate(&validator, &compiled_schema).map_err(|e| {
533 RudofError::SHACLValidationError {
534 error: format!("{e}"),
535 schema: Box::new(shacl_schema),
536 }
537 })?;
538 Ok(result)
539 }
540
541 pub fn validate_shex(&mut self) -> Result<ResultShapeMap> {
544 let schema_str = format!("{:?}", self.shex_validator);
545 match self.shex_validator {
546 None => Err(RudofError::ShExValidatorUndefined {}),
547 Some(ref mut validator) => match &self.shapemap {
548 None => Err(RudofError::NoShapeMap { schema: schema_str }),
549 Some(shapemap) => {
550 let schema = validator.schema().clone();
551 let result = validator
552 .validate_shapemap2(
553 shapemap,
554 &self.rdf_data,
555 &schema,
556 &Some(self.rdf_data.prefixmap_in_memory()),
557 &None, )
559 .map_err(|e| RudofError::ShExValidatorError {
560 schema: schema_str.clone(),
561 rdf_data: format!("{:?}", self.rdf_data),
562 query_map: format!("{shapemap:?}"),
563 error: format!("{e}"),
564 })?;
565 Ok(result.clone())
566 }
567 },
568 }
569 }
570
571 pub fn add_endpoint(&mut self, iri: &IriS, prefixmap: &PrefixMap) -> Result<()> {
573 let sparql_endpoint =
574 SRDFSparql::new(iri, prefixmap).map_err(|e| RudofError::AddingEndpointError {
575 iri: iri.clone(),
576 error: format!("{e}"),
577 })?;
578
579 self.rdf_data.add_endpoint(sparql_endpoint);
580 Ok(())
581 }
582
583 pub fn read_data<R: io::Read>(
585 &mut self,
586 reader: R,
587 format: &RDFFormat,
588 base: Option<&str>,
589 reader_mode: &ReaderMode,
590 ) -> Result<()> {
591 self.rdf_data
592 .merge_from_reader(reader, format, base, reader_mode)
593 .map_err(|e| RudofError::MergeRDFDataFromReader {
594 format: format!("{format:?}"),
595 base: format!("{base:?}"),
596 reader_mode: format!("{reader_mode:?}"),
597 error: format!("{e}"),
598 })?;
599 Ok(())
600 }
601
602 pub fn clean_rdf_graph(&mut self) {
604 self.rdf_data.clean_graph();
605 }
606
607 pub fn shapemap_add_node_shape_selectors(&mut self, node: NodeSelector, shape: ShapeSelector) {
609 match &mut self.shapemap {
610 None => {
611 let mut shapemap = QueryShapeMap::new();
612 shapemap.add_association(node, shape);
613 self.shapemap = Some(shapemap)
614 }
615 Some(ref mut sm) => {
616 sm.add_association(node, shape);
617 }
618 };
619 }
620
621 pub fn read_shapemap<R: io::Read>(
623 &mut self,
624 mut reader: R,
625 shapemap_format: &ShapeMapFormat,
626 ) -> Result<()> {
627 let mut v = Vec::new();
628 reader
629 .read_to_end(&mut v)
630 .map_err(|e| RudofError::ReadError {
631 error: format!("{e}"),
632 })?;
633 let s = String::from_utf8(v).map_err(|e| RudofError::Utf8Error {
634 error: format!("{e}"),
635 })?;
636 let shapemap = match shapemap_format {
637 ShapeMapFormat::Compact => {
638 let shapemap = ShapeMapParser::parse(
639 s.as_str(),
640 &Some(self.nodes_prefixmap()),
641 &self.shex_shapes_prefixmap(),
642 )
643 .map_err(|e| RudofError::ShapeMapParseError {
644 str: s.to_string(),
645 error: format!("{e}"),
646 })?;
647 Ok(shapemap)
648 }
649 ShapeMapFormat::JSON => todo!(),
650 }?;
651 self.shapemap = Some(shapemap);
652 Ok(())
653 }
654
655 pub fn reset_shapemap(&mut self) {
656 self.shapemap = None
657 }
658
659 pub fn nodes_prefixmap(&self) -> PrefixMap {
661 self.rdf_data.prefixmap_in_memory()
662 }
663
664 pub fn shex_shapes_prefixmap(&self) -> Option<PrefixMap> {
668 self.shex_validator
669 .as_ref()
670 .map(|validator| validator.shapes_prefixmap())
671 }
672
673 pub fn get_rdf_data(&self) -> &RdfData {
675 &self.rdf_data
676 }
677
678 pub fn shex_schema_without_imports(&mut self) -> Result<SchemaWithoutImports> {
682 match &self.resolved_shex_schema {
683 None => match &self.shex_schema {
684 Some(schema) => {
685 let schema_resolved = SchemaWithoutImports::resolve_imports(
686 schema,
687 &Some(schema.source_iri()),
688 Some(&ResolveMethod::default()),
689 )
690 .map_err(|e| RudofError::ResolvingImportsShExSchema {
691 error: format!("{e}"),
692 })?;
693 self.resolved_shex_schema = Some(schema_resolved.clone());
694 Ok(schema_resolved)
695 }
696 None => Err(RudofError::NoShExSchemaForResolvingImports),
697 },
698 Some(resolved_schema) => Ok(resolved_schema.clone()),
699 }
700 }
701}
702
703fn shacl_schema_from_data<RDF: FocusRDF + Debug>(rdf_data: RDF) -> Result<ShaclSchema> {
704 let schema = ShaclParser::new(rdf_data)
705 .parse()
706 .map_err(|e| RudofError::SHACLParseError {
707 error: format!("{e}"),
708 })?;
709 Ok(schema)
710}
711
712fn shacl_format2rdf_format(shacl_format: &ShaclFormat) -> Result<RDFFormat> {
713 match shacl_format {
714 ShaclFormat::N3 => Ok(RDFFormat::N3),
715 ShaclFormat::NQuads => Ok(RDFFormat::NQuads),
716 ShaclFormat::NTriples => Ok(RDFFormat::NTriples),
717 ShaclFormat::RDFXML => Ok(RDFFormat::RDFXML),
718 ShaclFormat::TriG => Ok(RDFFormat::TriG),
719 ShaclFormat::Turtle => Ok(RDFFormat::Turtle),
720 ShaclFormat::Internal => Err(RudofError::NoInternalFormatForRDF),
721 }
722}
723
724#[cfg(test)]
725mod tests {
726 use iri_s::iri;
727 use shacl_ast::ShaclFormat;
728 use shacl_validation::shacl_processor::ShaclValidationMode;
729 use shapemap::ShapeMapFormat;
730 use shex_ast::{ir::shape_label::ShapeLabel, Node};
731 use shex_validation::ShExFormat;
732
733 use crate::RudofConfig;
734
735 use super::Rudof;
736
737 #[test]
738 fn test_shex_validation_ok() {
739 let data = r#"<http://example/x> <http://example/p> 23 ."#;
740 let shex = r#"<http://example/S> { <http://example/p> . }"#;
741 let shapemap = r#"<http://example/x>@<http://example/S>"#;
742 let mut rudof = Rudof::new(&RudofConfig::default());
743 rudof
744 .read_data(
745 data.as_bytes(),
746 &srdf::RDFFormat::Turtle,
747 None,
748 &srdf::ReaderMode::Strict,
749 )
750 .unwrap();
751
752 rudof
753 .read_shex(shex.as_bytes(), &ShExFormat::ShExC, None)
754 .unwrap();
755 rudof
756 .read_shapemap(shapemap.as_bytes(), &ShapeMapFormat::default())
757 .unwrap();
758 let result = rudof.validate_shex().unwrap();
759 let node = Node::iri(iri!("http://example/x"));
760 let shape = ShapeLabel::iri(iri!("http://example/S"));
761 assert!(result.get_info(&node, &shape).unwrap().is_conformant())
762 }
763
764 #[test]
765 fn test_shex_validation_ko() {
766 let data = r#"<http://example/x> <http://example/other> 23 ."#;
767 let shex = r#"<http://example/S> { <http://example/p> . }"#;
768 let shapemap = r#"<http://example/x>@<http://example/S>"#;
769 let mut rudof = Rudof::new(&RudofConfig::default());
770 rudof
771 .read_data(
772 data.as_bytes(),
773 &srdf::RDFFormat::Turtle,
774 None,
775 &srdf::ReaderMode::Strict,
776 )
777 .unwrap();
778
779 rudof
780 .read_shex(shex.as_bytes(), &ShExFormat::ShExC, None)
781 .unwrap();
782 rudof
783 .read_shapemap(shapemap.as_bytes(), &ShapeMapFormat::default())
784 .unwrap();
785 let result = rudof.validate_shex().unwrap();
786 let node = Node::iri(iri!("http://example/x"));
787 let shape = ShapeLabel::iri(iri!("http://example/S"));
788 assert!(result.get_info(&node, &shape).unwrap().is_non_conformant(),)
789 }
790
791 #[test]
792 fn test_shacl_validation_ok() {
793 let data = r#"prefix : <http://example.org/>
794 :x :p 23 .
795 "#;
796 let shacl = r#"prefix : <http://example.org/>
797 prefix sh: <http://www.w3.org/ns/shacl#>
798 prefix xsd: <http://www.w3.org/2001/XMLSchema#>
799
800 :S a sh:NodeShape; sh:closed true ;
801 sh:targetNode :x ;
802 sh:property [
803 sh:path :p ;
804 sh:minCount 1;
805 sh:maxCount 1;
806 sh:datatype xsd:integer ;
807 ] .
808 "#;
809 let mut rudof = Rudof::new(&RudofConfig::default());
810 rudof
811 .read_data(
812 data.as_bytes(),
813 &srdf::RDFFormat::Turtle,
814 None,
815 &srdf::ReaderMode::Strict,
816 )
817 .unwrap();
818
819 rudof
820 .read_shacl(
821 shacl.as_bytes(),
822 &ShaclFormat::Turtle,
823 None,
824 &srdf::ReaderMode::Lax,
825 )
826 .unwrap();
827 let result = rudof
828 .validate_shacl(
829 &ShaclValidationMode::Native,
830 &crate::ShapesGraphSource::CurrentSchema,
831 )
832 .unwrap();
833 assert!(result.results().is_empty())
834 }
835
836 #[test]
837 fn test_shacl_validation_ko() {
838 let data = r#"prefix : <http://example.org/>
839 :x :other 23 .
840 "#;
841 let shacl = r#"prefix : <http://example.org/>
842 prefix sh: <http://www.w3.org/ns/shacl#>
843 prefix xsd: <http://www.w3.org/2001/XMLSchema#>
844
845 :S a sh:NodeShape;
846 sh:targetNode :x ;
847 sh:property [
848 sh:path :p ;
849 sh:minCount 1;
850 sh:maxCount 1;
851 sh:datatype xsd:integer ;
852 ] .
853 "#;
854 let mut rudof = Rudof::new(&RudofConfig::default());
855 rudof
856 .read_data(
857 data.as_bytes(),
858 &srdf::RDFFormat::Turtle,
859 None,
860 &srdf::ReaderMode::Strict,
861 )
862 .unwrap();
863
864 rudof
865 .read_shacl(
866 shacl.as_bytes(),
867 &ShaclFormat::Turtle,
868 None,
869 &srdf::ReaderMode::Lax,
870 )
871 .unwrap();
872 let result = rudof
873 .validate_shacl(
874 &ShaclValidationMode::Native,
875 &crate::ShapesGraphSource::CurrentSchema,
876 )
877 .unwrap();
878 assert!(!result.conforms())
879 }
880
881 #[test]
882 fn test_shacl_validation_data_ko() {
883 let data = r#"prefix : <http://example.org/>
884 prefix sh: <http://www.w3.org/ns/shacl#>
885 prefix xsd: <http://www.w3.org/2001/XMLSchema#>
886
887 :x :other 23 .
888
889 :S a sh:NodeShape;
890 sh:targetNode :x ;
891 sh:property [
892 sh:path :p ;
893 sh:minCount 1;
894 sh:maxCount 1;
895 sh:datatype xsd:integer ;
896 ] .
897 "#;
898 let mut rudof = Rudof::new(&RudofConfig::default());
899 rudof
900 .read_data(
901 data.as_bytes(),
902 &srdf::RDFFormat::Turtle,
903 None,
904 &srdf::ReaderMode::Strict,
905 )
906 .unwrap();
907 let result = rudof
908 .validate_shacl(
909 &ShaclValidationMode::Native,
910 &crate::ShapesGraphSource::CurrentData,
911 )
912 .unwrap();
913 assert!(!result.conforms())
914 }
915
916 #[test]
917 fn test_shacl_validation_data_ok() {
918 let data = r#"prefix : <http://example.org/>
919 prefix sh: <http://www.w3.org/ns/shacl#>
920 prefix xsd: <http://www.w3.org/2001/XMLSchema#>
921
922 :x :p 23 .
923
924 :S a sh:NodeShape;
925 sh:targetNode :x ;
926 sh:property [
927 sh:path :p ;
928 sh:minCount 1;
929 sh:maxCount 1;
930 sh:datatype xsd:integer ;
931 ] .
932 "#;
933 let mut rudof = Rudof::new(&RudofConfig::default());
934 rudof
935 .read_data(
936 data.as_bytes(),
937 &srdf::RDFFormat::Turtle,
938 None,
939 &srdf::ReaderMode::Strict,
940 )
941 .unwrap();
942 let result = rudof
943 .validate_shacl(
944 &ShaclValidationMode::Native,
945 &crate::ShapesGraphSource::CurrentData,
946 )
947 .unwrap();
948 assert!(result.conforms())
949 }
950}