1use crate::async_srdf::AsyncSRDF;
2use crate::{FocusRDF, Query, RDFFormat, Rdf, SRDFBuilder, RDF_TYPE_STR};
3use async_trait::async_trait;
4use colored::*;
5use iri_s::IriS;
6use oxrdfio::{RdfFormat, RdfSerializer};
7use oxrdfxml::RdfXmlParser;
8use std::collections::{HashMap, HashSet};
9use std::fs::File;
10use std::io::{self, BufReader, Write};
11use std::path::{Path, PathBuf};
12use std::str::FromStr;
13use tracing::debug;
14
15use crate::srdfgraph_error::SRDFGraphError;
16use oxrdf::{
17 BlankNode as OxBlankNode, Graph, GraphName, Literal as OxLiteral, NamedNode as OxNamedNode,
18 NamedNodeRef, Quad, Subject as OxSubject, SubjectRef, Term as OxTerm, TermRef,
19 Triple as OxTriple, TripleRef,
20};
21use oxttl::{NQuadsParser, NTriplesParser, TurtleParser};
22use prefixmap::{prefixmap::*, PrefixMapError};
23
24#[derive(Debug, Default, Clone)]
25pub struct SRDFGraph {
26 focus: Option<OxTerm>,
27 graph: Graph,
28 pm: PrefixMap,
29 base: Option<IriS>,
30 bnode_counter: usize,
31}
32
33impl SRDFGraph {
34 pub fn new() -> Self {
35 Self::default()
36 }
37
38 pub fn len(&self) -> usize {
39 self.graph.len()
40 }
41
42 pub fn quads(&self) -> impl Iterator<Item = Quad> + '_ {
43 let graph_name = GraphName::DefaultGraph;
44 self.graph
45 .iter()
46 .map(move |t| triple_to_quad(t, graph_name.clone()))
47 }
48
49 pub fn is_empty(&self) -> bool {
50 self.graph.is_empty()
51 }
52
53 pub fn merge_from_reader<R: io::Read>(
54 &mut self,
55 read: R,
56 format: &RDFFormat,
57 base: Option<&str>,
58 reader_mode: &ReaderMode,
59 ) -> Result<(), SRDFGraphError> {
60 match format {
61 RDFFormat::Turtle => {
62 let turtle_parser = match base {
63 None => TurtleParser::new(),
64 Some(iri) => TurtleParser::new().with_base_iri(iri)?,
65 };
66 let mut reader = turtle_parser.for_reader(read);
68 for triple_result in reader.by_ref() {
69 self.graph.insert(triple_result?.as_ref());
70 }
71 let prefixes: HashMap<&str, &str> = reader.prefixes().collect();
72 self.base = match (&self.base, base) {
73 (None, None) => None,
74 (Some(b), None) => Some(b.clone()),
75 (_, Some(b)) => Some(IriS::new_unchecked(b)),
76 };
77 let pm = PrefixMap::from_hashmap(&prefixes)?;
78 self.merge_prefixes(pm)?;
79 }
80 RDFFormat::NTriples => {
81 let parser = NTriplesParser::new();
82 let mut reader = parser.for_reader(read);
83 for triple_result in reader.by_ref() {
84 match triple_result {
85 Err(e) => {
86 if reader_mode.is_strict() {
87 return Err(SRDFGraphError::TurtleError {
88 data: "Reading n-quads".to_string(),
89 turtle_error: e,
90 });
91 } else {
92 debug!("Error captured: {e:?}")
93 }
94 }
95 Ok(t) => {
96 self.graph.insert(t.as_ref());
97 }
98 }
99 }
100 }
101 RDFFormat::RDFXML => {
102 let parser = RdfXmlParser::new();
103 let mut reader = parser.for_reader(read);
104 for triple_result in reader.by_ref() {
105 match triple_result {
106 Err(e) => {
107 debug!("Error captured: {e:?}")
108 }
109 Ok(t) => {
110 self.graph.insert(t.as_ref());
111 }
112 }
113 }
114 }
115 RDFFormat::TriG => todo!(),
116 RDFFormat::N3 => todo!(),
117 RDFFormat::NQuads => {
118 let parser = NQuadsParser::new();
119 let mut reader = parser.for_reader(read);
120 for triple_result in reader.by_ref() {
121 match triple_result {
122 Err(e) => {
123 debug!("Error captured: {e:?}")
124 }
125 Ok(t) => {
126 self.graph.insert(t.as_ref());
127 }
128 }
129 }
130 }
131 }
132 Ok(())
133 }
134
135 pub fn merge_prefixes(&mut self, prefixmap: PrefixMap) -> Result<(), SRDFGraphError> {
136 self.pm.merge(prefixmap)?;
137 Ok(())
138 }
139
140 pub fn from_reader<R: io::Read>(
141 read: R,
142 format: &RDFFormat,
143 base: Option<&str>,
144 reader_mode: &ReaderMode,
145 ) -> Result<SRDFGraph, SRDFGraphError> {
146 let mut srdf_graph = SRDFGraph::new();
147
148 srdf_graph.merge_from_reader(read, format, base, reader_mode)?;
149 Ok(srdf_graph)
150 }
151
152 pub fn resolve(&self, str: &str) -> Result<OxNamedNode, SRDFGraphError> {
153 let r = self.pm.resolve(str)?;
154 Ok(Self::cnv_iri(r))
155 }
156
157 pub fn show_blanknode(&self, bn: &OxBlankNode) -> String {
158 let str: String = format!("{}", bn);
159 format!("{}", str.green())
160 }
161
162 pub fn show_literal(&self, lit: &OxLiteral) -> String {
163 let str: String = format!("{}", lit);
164 format!("{}", str.red())
165 }
166
167 pub fn from_str(
168 data: &str,
169 format: &RDFFormat,
170 base: Option<&str>,
171 reader_mode: &ReaderMode,
172 ) -> Result<SRDFGraph, SRDFGraphError> {
173 Self::from_reader(std::io::Cursor::new(&data), format, base, reader_mode)
174 }
175
176 fn cnv_iri(iri: IriS) -> OxNamedNode {
177 OxNamedNode::new_unchecked(iri.as_str())
178 }
179
180 pub fn add_triple_ref<'a, S, P, O>(
181 &mut self,
182 subj: S,
183 pred: P,
184 obj: O,
185 ) -> Result<(), SRDFGraphError>
186 where
187 S: Into<SubjectRef<'a>>,
188 P: Into<NamedNodeRef<'a>>,
189 O: Into<TermRef<'a>>,
190 {
191 let subj: SubjectRef<'a> = subj.into();
192 let pred: NamedNodeRef<'a> = pred.into();
193 let obj: TermRef<'a> = obj.into();
194 let triple = TripleRef::new(subj, pred, obj);
195 self.graph.insert(triple);
196 Ok(())
197 }
198
199 pub fn merge_from_path<P: AsRef<Path>>(
200 &mut self,
201 path: P,
202 format: &RDFFormat,
203 base: Option<&str>,
204 reader_mode: &ReaderMode,
205 ) -> Result<(), SRDFGraphError> {
206 let path_name = path.as_ref().display();
207 let file = File::open(path.as_ref()).map_err(|e| SRDFGraphError::ReadingPathError {
208 path_name: path_name.to_string(),
209 error: e,
210 })?;
211 let reader = BufReader::new(file);
212 Self::merge_from_reader(self, reader, format, base, reader_mode)?;
213 Ok(())
214 }
215
216 pub fn from_path<P: AsRef<Path>>(
217 path: P,
218 format: &RDFFormat,
219 base: Option<&str>,
220 reader_mode: &ReaderMode,
221 ) -> Result<SRDFGraph, SRDFGraphError> {
222 let path_name = path.as_ref().display();
223 let file = File::open(path.as_ref()).map_err(|e| SRDFGraphError::ReadingPathError {
224 path_name: path_name.to_string(),
225 error: e,
226 })?;
227 let reader = BufReader::new(file);
228 Self::from_reader(reader, format, base, reader_mode)
229 }
230
231 pub fn parse_data(
232 data: &String,
233 format: &RDFFormat,
234 base: &Path,
235 reader_mode: &ReaderMode,
236 ) -> Result<SRDFGraph, SRDFGraphError> {
237 let mut attempt = PathBuf::from(base);
238 attempt.push(data);
239 let base = Some("base:://");
240 let data_path = &attempt;
241 let graph = Self::from_path(data_path, format, base, reader_mode)?;
242 Ok(graph)
243 }
244
245 pub fn prefixmap(&self) -> PrefixMap {
246 self.pm.clone()
247 }
248}
249
250impl Rdf for SRDFGraph {
251 type IRI = OxNamedNode;
252 type BNode = OxBlankNode;
253 type Literal = OxLiteral;
254 type Subject = OxSubject;
255 type Term = OxTerm;
256 type Triple = OxTriple;
257 type Err = SRDFGraphError;
258
259 fn resolve_prefix_local(&self, prefix: &str, local: &str) -> Result<IriS, PrefixMapError> {
260 let iri = self.pm.resolve_prefix_local(prefix, local)?;
261 Ok(iri.clone())
262 }
263
264 fn qualify_iri(&self, node: &Self::IRI) -> String {
265 let iri = IriS::from_str(node.as_str()).unwrap();
266 self.pm.qualify(&iri)
267 }
268
269 fn qualify_subject(&self, subj: &OxSubject) -> String {
270 match subj {
271 OxSubject::BlankNode(bn) => self.show_blanknode(bn),
272 OxSubject::NamedNode(n) => self.qualify_iri(n),
273 #[cfg(feature = "rdf-star")]
274 OxSubject::Triple(_) => unimplemented!(),
275 }
276 }
277
278 fn qualify_term(&self, term: &OxTerm) -> String {
279 match term {
280 OxTerm::BlankNode(bn) => self.show_blanknode(bn),
281 OxTerm::Literal(lit) => self.show_literal(lit),
282 OxTerm::NamedNode(n) => self.qualify_iri(n),
283 #[cfg(feature = "rdf-star")]
284 OxTerm::Triple(_) => unimplemented!(),
285 }
286 }
287
288 fn prefixmap(&self) -> Option<prefixmap::PrefixMap> {
289 Some(self.pm.clone())
290 }
291}
292
293impl Query for SRDFGraph {
294 fn triples(&self) -> Result<impl Iterator<Item = Self::Triple>, Self::Err> {
295 Ok(self.graph.iter().map(TripleRef::into_owned))
296 }
297}
298
299#[async_trait]
300impl AsyncSRDF for SRDFGraph {
301 type IRI = OxNamedNode;
302 type BNode = OxBlankNode;
303 type Literal = OxLiteral;
304 type Subject = OxSubject;
305 type Term = OxTerm;
306 type Err = SRDFGraphError;
307
308 async fn get_predicates_subject(
309 &self,
310 subject: &OxSubject,
311 ) -> Result<HashSet<OxNamedNode>, SRDFGraphError> {
312 let mut results = HashSet::new();
313 for triple in self.graph.triples_for_subject(subject) {
314 let predicate: OxNamedNode = triple.predicate.to_owned().into();
315 results.insert(predicate);
316 }
317 Ok(results)
318 }
319
320 async fn get_objects_for_subject_predicate(
321 &self,
322 subject: &OxSubject,
323 pred: &OxNamedNode,
324 ) -> Result<HashSet<OxTerm>, SRDFGraphError> {
325 let mut results = HashSet::new();
326 for triple in self.graph.triples_for_subject(subject) {
327 let predicate: OxNamedNode = triple.predicate.to_owned().into();
328 if predicate.eq(pred) {
329 let object: OxTerm = triple.object.to_owned().into();
330 results.insert(object);
331 }
332 }
333 Ok(results)
334 }
335
336 async fn get_subjects_for_object_predicate(
337 &self,
338 object: &OxTerm,
339 pred: &OxNamedNode,
340 ) -> Result<HashSet<OxSubject>, SRDFGraphError> {
341 let mut results = HashSet::new();
342 for triple in self.graph.triples_for_object(object) {
343 let predicate: OxNamedNode = triple.predicate.to_owned().into();
344 if predicate.eq(pred) {
345 let subject: OxSubject = triple.subject.to_owned().into();
346 results.insert(subject);
347 }
348 }
349 Ok(results)
350 }
351}
352
353impl FocusRDF for SRDFGraph {
354 fn set_focus(&mut self, focus: &Self::Term) {
355 self.focus = Some(focus.clone())
356 }
357
358 fn get_focus(&self) -> &Option<Self::Term> {
359 &self.focus
360 }
361}
362
363impl SRDFBuilder for SRDFGraph {
364 fn add_base(&mut self, base: &Option<IriS>) -> Result<(), Self::Err> {
365 self.base.clone_from(base);
366 Ok(())
367 }
368
369 fn add_prefix(&mut self, alias: &str, iri: &IriS) -> Result<(), Self::Err> {
370 self.pm.insert(alias, iri)?;
371 Ok(())
372 }
373
374 fn add_prefix_map(&mut self, prefix_map: PrefixMap) -> Result<(), Self::Err> {
375 self.pm = prefix_map.clone();
376 Ok(())
377 }
378
379 fn add_bnode(&mut self) -> Result<Self::BNode, Self::Err> {
380 self.bnode_counter += 1;
381 match self.bnode_counter.try_into() {
382 Ok(bn) => Ok(OxBlankNode::new_from_unique_id(bn)),
383 Err(_) => Err(SRDFGraphError::BlankNodeId {
384 msg: format!("Error converting {} to usize", self.bnode_counter),
385 }),
386 }
387 }
388
389 fn add_triple<S, P, O>(&mut self, subj: S, pred: P, obj: O) -> Result<(), Self::Err>
390 where
391 S: Into<Self::Subject>,
392 P: Into<Self::IRI>,
393 O: Into<Self::Term>,
394 {
395 let triple = OxTriple::new(subj.into(), pred.into(), obj.into());
396 self.graph.insert(&triple);
397 Ok(())
398 }
399
400 fn remove_triple<S, P, O>(&mut self, subj: S, pred: P, obj: O) -> Result<(), Self::Err>
401 where
402 S: Into<Self::Subject>,
403 P: Into<Self::IRI>,
404 O: Into<Self::Term>,
405 {
406 let triple = OxTriple::new(subj.into(), pred.into(), obj.into());
407 self.graph.remove(&triple);
408 Ok(())
409 }
410
411 fn add_type<S, T>(&mut self, node: S, type_: T) -> Result<(), Self::Err>
412 where
413 S: Into<Self::Subject>,
414 T: Into<Self::Term>,
415 {
416 let subject: Self::Subject = node.into();
417 let type_: Self::Term = type_.into();
418 let triple = OxTriple::new(subject, rdf_type(), type_.clone());
419 self.graph.insert(&triple);
420 Ok(())
421 }
422
423 fn empty() -> Self {
424 SRDFGraph {
425 focus: None,
426 graph: Graph::new(),
427 pm: PrefixMap::new(),
428 base: None,
429 bnode_counter: 0,
430 }
431 }
432
433 fn serialize<W: Write>(&self, format: &RDFFormat, write: &mut W) -> Result<(), Self::Err> {
434 let mut serializer = RdfSerializer::from_format(cnv_rdf_format(format));
435
436 for (prefix, iri) in &self.pm.map {
437 serializer = serializer.with_prefix(prefix, iri.as_str()).unwrap();
438 }
439
440 let mut writer = serializer.for_writer(write);
441 for triple in self.graph.iter() {
442 writer.serialize_triple(triple)?;
443 }
444 writer.finish()?;
445 Ok(())
446 }
447}
448
449fn cnv_rdf_format(rdf_format: &RDFFormat) -> RdfFormat {
450 match rdf_format {
451 RDFFormat::NTriples => RdfFormat::NTriples,
452 RDFFormat::Turtle => RdfFormat::Turtle,
453 RDFFormat::RDFXML => RdfFormat::RdfXml,
454 RDFFormat::TriG => RdfFormat::TriG,
455 RDFFormat::N3 => RdfFormat::N3,
456 RDFFormat::NQuads => RdfFormat::NQuads,
457 }
458}
459
460fn rdf_type() -> OxNamedNode {
461 OxNamedNode::new_unchecked(RDF_TYPE_STR)
462}
463
464fn triple_to_quad(t: TripleRef, graph_name: GraphName) -> Quad {
465 let subj: oxrdf::Subject = t.subject.into();
466 let pred: oxrdf::NamedNode = t.predicate.into();
467 let obj: oxrdf::Term = t.object.into();
468 Quad::new(subj, pred, obj, graph_name)
469}
470
471#[derive(Debug, PartialEq, Clone, Default)]
473pub enum ReaderMode {
474 #[default]
476 Strict,
477
478 Lax,
480}
481
482impl ReaderMode {
483 pub fn is_strict(&self) -> bool {
484 matches!(self, ReaderMode::Strict)
485 }
486}
487
488#[cfg(test)]
489mod tests {
490 use std::collections::HashSet;
491
492 use iri_s::IriS;
493 use oxrdf::Literal as OxLiteral;
494 use oxrdf::NamedNode as OxNamedNode;
495 use oxrdf::Subject as OxSubject;
496 use oxrdf::Term as OxTerm;
497
498 use crate::iri;
499 use crate::matcher::Any;
500 use crate::not;
501 use crate::ok;
502 use crate::property_bool;
503 use crate::property_integer;
504 use crate::property_integers;
505 use crate::property_string;
506 use crate::property_value;
507 use crate::rdf_list;
508 use crate::rdf_parser;
509 use crate::satisfy;
510 use crate::set_focus;
511 use crate::PResult;
512 use crate::Query as _;
513 use crate::RDFFormat;
514 use crate::RDFNodeParse as _;
515 use crate::RDFParseError;
516 use crate::SRDFBuilder;
517 use crate::Triple;
518
519 use super::ReaderMode;
520 use super::SRDFGraph;
521
522 const DUMMY_GRAPH: &str = r#"
523 prefix : <http://example.org/>
524 :x :p 1 .
525 :y :p "String" .
526 :y :q 2 .
527 :z :r 3 .
528 :x :s 4 .
529 "#;
530
531 const DUMMY_GRAPH_1: &str = r#"
532 prefix : <http://example.org/>
533 prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
534 :x :p [ :p 1 ] .
535 "#;
536
537 const DUMMY_GRAPH_2: &str = r#"
538 prefix : <http://example.org/>
539 :x :p (1 2) .
540 "#;
541
542 const DUMMY_GRAPH_3: &str = r#"
543 prefix : <http://example.org/>
544 :x :p 1, 2, 3, 2 .
545 "#;
546
547 const DUMMY_GRAPH_4: &str = r#"
548 prefix : <http://example.org/>
549 :x :p 1, 2, 3 .
550 "#;
551
552 const DUMMY_GRAPH_5: &str = r#"
553 prefix : <http://example.org/>
554 :x :p 1, 2 ;
555 :q true .
556 "#;
557
558 const DUMMY_GRAPH_6: &str = r#"
559 prefix : <http://example.org/>
560 :x :p 1 .
561 "#;
562
563 const DUMMY_GRAPH_7: &str = r#"
564 prefix : <http://example.org/>
565 :x :p true .
566 "#;
567
568 const DUMMY_GRAPH_8: &str = r#"
569 prefix : <http://example.org/>
570 :x :p true ;
571 :q 1 .
572 "#;
573
574 const DUMMY_GRAPH_9: &str = r#"
575 prefix : <http://example.org/>
576 :x :p 1 .
577 "#;
578
579 const DUMMY_GRAPH_10: &str = r#"
580 prefix : <http://example.org/>
581 :x :p "1" .
582 "#;
583
584 #[derive(Debug, PartialEq)]
585 enum A {
586 Int(isize),
587 Bool(bool),
588 }
589
590 fn graph_from_str(s: &str) -> SRDFGraph {
591 SRDFGraph::from_str(s, &RDFFormat::Turtle, None, &ReaderMode::Strict).unwrap()
592 }
593
594 #[test]
595 fn test_triples_matching_subject_predicate_and_object() {
596 let graph = graph_from_str(DUMMY_GRAPH);
597 let x: OxSubject = OxNamedNode::new_unchecked("http://example.org/x").into();
598 let p = OxNamedNode::new_unchecked("http://example.org/p");
599 let one: OxTerm = OxLiteral::from(1).into();
600 let triples = graph.triples_matching(x, p, one).unwrap();
601 assert_eq!(triples.count(), 1)
602 }
603
604 #[test]
605 fn test_triples_matching_subject_and_predicate() {
606 let graph = graph_from_str(DUMMY_GRAPH);
607 let x: OxSubject = OxNamedNode::new_unchecked("http://example.org/x").into();
608 let p = OxNamedNode::new_unchecked("http://example.org/p");
609 let triples = graph.triples_matching(x, p, Any).unwrap();
610 assert_eq!(triples.count(), 1)
611 }
612
613 #[test]
614 fn test_triples_matching_subject_and_object() {
615 let graph = graph_from_str(DUMMY_GRAPH);
616 let x: OxSubject = OxNamedNode::new_unchecked("http://example.org/x").into();
617 let one: OxTerm = OxLiteral::from(1).into();
618 let triples = graph.triples_matching(x, Any, one).unwrap();
619 assert_eq!(triples.count(), 1)
620 }
621
622 #[test]
623 fn test_triples_matching_predicate_and_object() {
624 let graph = graph_from_str(DUMMY_GRAPH);
625 let p = OxNamedNode::new_unchecked("http://example.org/p");
626 let one: OxTerm = OxLiteral::from(1).into();
627 let triples = graph.triples_matching(Any, p, one).unwrap();
628 assert_eq!(triples.count(), 1)
629 }
630
631 #[test]
632 fn test_triples_matching_subject() {
633 let graph = graph_from_str(DUMMY_GRAPH);
634 let x: OxSubject = OxNamedNode::new_unchecked("http://example.org/x").into();
635 let triples = graph.triples_matching(x, Any, Any).unwrap();
636 assert_eq!(triples.count(), 2)
637 }
638
639 #[test]
640 fn test_triples_matching_predicate() {
641 let graph = graph_from_str(DUMMY_GRAPH);
642 let p = OxNamedNode::new_unchecked("http://example.org/p");
643 let triples = graph.triples_matching(Any, p, Any).unwrap();
644 assert_eq!(triples.count(), 2)
645 }
646
647 #[test]
648 fn test_triples_matching_object() {
649 let graph = graph_from_str(DUMMY_GRAPH);
650 let one: OxTerm = OxLiteral::from(1).into();
651 let triples = graph.triples_matching(Any, Any, one).unwrap();
652 assert_eq!(triples.count(), 1)
653 }
654
655 #[test]
656 fn test_incoming_arcs() {
657 let graph = graph_from_str(DUMMY_GRAPH);
658 let x = OxSubject::NamedNode(OxNamedNode::new_unchecked("http://example.org/x"));
659 let p = OxNamedNode::new_unchecked("http://example.org/p");
660 let one: OxTerm = OxLiteral::from(1).into();
661 let actual = graph.incoming_arcs(one).unwrap();
662 let expected = HashSet::from([x]);
663 assert_eq!(actual.get(&p), Some(&expected))
664 }
665
666 #[test]
667 fn test_outgoing_arcs() {
668 let graph = graph_from_str(DUMMY_GRAPH_1);
669
670 let x = OxSubject::NamedNode(OxNamedNode::new_unchecked("http://example.org/x"));
671 let p = OxNamedNode::new_unchecked("http://example.org/p");
672 let one: OxTerm = OxLiteral::from(1).into();
673
674 let subject = graph
675 .triples_matching(x, p.clone(), Any)
676 .unwrap()
677 .map(Triple::into_object)
678 .next()
679 .unwrap()
680 .try_into()
681 .unwrap();
682
683 let actual = graph.outgoing_arcs(subject).unwrap();
684 let expected = HashSet::from([one]);
685
686 assert_eq!(actual.get(&p), Some(&expected))
687 }
688
689 #[test]
690 fn test_add_triple() {
691 let mut graph = SRDFGraph::default();
692
693 let alice = OxSubject::NamedNode(OxNamedNode::new_unchecked("http://example.org/alice"));
694 let knows = OxNamedNode::new_unchecked("http://example.org/knows");
695 let bob = OxTerm::NamedNode(OxNamedNode::new_unchecked("http://example.org/bob"));
696
697 graph.add_triple(alice, knows, bob).unwrap();
698
699 assert_eq!(graph.len(), 1);
700 }
701
702 #[test]
703 fn test_rdf_list() {
704 let graph = graph_from_str(DUMMY_GRAPH_2);
705
706 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
707 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
708
709 let mut parser = property_value(&p).then(move |obj| set_focus(&obj).with(rdf_list()));
710 let result: Vec<OxTerm> = parser.parse(&x, graph).unwrap();
711
712 assert_eq!(
713 result,
714 vec![
715 OxTerm::from(OxLiteral::from(1)),
716 OxTerm::from(OxLiteral::from(2))
717 ]
718 )
719 }
720
721 #[test]
722 fn test_parser() {
723 rdf_parser! {
724 fn my_ok['a, A, RDF](value: &'a A)(RDF) -> A
725 where [
726 A: Clone
727 ] { ok(&value.clone()) }
728 }
729 let graph = graph_from_str("prefix : <http://example.org/>");
730 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
731 assert_eq!(my_ok(&3).parse(&x, graph).unwrap(), 3)
732 }
733
734 #[test]
735 fn test_parser_property_integers() {
736 let graph = graph_from_str(DUMMY_GRAPH_3);
737 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
738 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
739 let mut parser = property_integers(&p);
740 assert_eq!(parser.parse(&x, graph).unwrap(), HashSet::from([1, 2, 3]))
741 }
742
743 #[test]
744 fn test_parser_then_mut() {
745 let graph = graph_from_str(DUMMY_GRAPH_4);
746 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
747 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
748
749 let mut parser = property_integers(&p).then_mut(move |ns| {
750 ns.extend(vec![4, 5]);
751 ok(ns)
752 });
753
754 assert_eq!(
755 parser.parse(&x, graph).unwrap(),
756 HashSet::from([1, 2, 3, 4, 5])
757 )
758 }
759
760 #[test]
761 fn test_parser_or() {
762 let graph = graph_from_str(DUMMY_GRAPH_5);
763 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
764 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
765 let q = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/q"));
766 let mut parser = property_bool(&p).or(property_bool(&q));
767 assert!(parser.parse(&x, graph).unwrap())
768 }
769
770 #[test]
771 fn test_parser_or_enum_1() {
772 let graph = graph_from_str(DUMMY_GRAPH_6);
773 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
774 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
775 let parser_a_bool = property_bool(&p).map(A::Bool);
776 let parser_a_int = property_integer(&p).map(A::Int);
777 let mut parser = parser_a_int.or(parser_a_bool);
778 assert_eq!(parser.parse(&x, graph).unwrap(), A::Int(1))
779 }
780
781 #[test]
782 fn test_parser_or_enum_2() {
783 let graph = graph_from_str(DUMMY_GRAPH_7);
784 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
785 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
786 let parser_a_bool = property_bool(&p).map(A::Bool);
787 let parser_a_int = property_integer(&p).map(A::Int);
788 let mut parser = parser_a_int.or(parser_a_bool);
789 assert_eq!(parser.parse(&x, graph).unwrap(), A::Bool(true))
790 }
791
792 #[test]
793 fn test_parser_and() {
794 let graph = graph_from_str(DUMMY_GRAPH_8);
795 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
796 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
797 let q = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/q"));
798 let mut parser = property_bool(&p).and(property_integer(&q));
799 assert_eq!(parser.parse(&x, graph).unwrap(), (true, 1))
800 }
801
802 #[test]
803 fn test_parser_map() {
804 let graph = graph_from_str(DUMMY_GRAPH_9);
805 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
806 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
807 let mut parser = property_integer(&p).map(|n| n + 1);
808 assert_eq!(parser.parse(&x, graph).unwrap(), 2)
809 }
810
811 #[test]
812 fn test_parser_and_then() {
813 let graph = graph_from_str(DUMMY_GRAPH_10);
814 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
815 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
816
817 struct IntConversionError(String);
818
819 fn cnv_int(s: String) -> Result<isize, IntConversionError> {
820 s.parse().map_err(|_| IntConversionError(s))
821 }
822
823 impl From<IntConversionError> for RDFParseError {
824 fn from(error: IntConversionError) -> RDFParseError {
825 RDFParseError::Custom {
826 msg: format!("Int conversion error: {}", error.0),
827 }
828 }
829 }
830
831 let mut parser = property_string(&p).and_then(cnv_int);
832 assert_eq!(parser.parse(&x, graph).unwrap(), 1)
833 }
834
835 #[test]
836 fn test_parser_flat_map() {
837 let graph = graph_from_str(DUMMY_GRAPH_10);
838 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
839 let p = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/p"));
840
841 fn cnv_int(s: String) -> PResult<isize> {
842 s.parse().map_err(|_| RDFParseError::Custom {
843 msg: format!("Error converting {s}"),
844 })
845 }
846
847 let mut parser = property_string(&p).flat_map(cnv_int);
848 assert_eq!(parser.parse(&x, graph).unwrap(), 1)
849 }
850
851 #[test]
852 fn test_rdf_parser_macro() {
853 rdf_parser! {
854 fn is_term['a, RDF](term: &'a RDF::Term)(RDF) -> ()
855 where [
856 ] {
857 let name = format!("is_{term}");
858 satisfy(|t| { t == *term }, name.as_str())
859 }
860 }
861
862 let graph = graph_from_str(DUMMY_GRAPH_9);
863 let x = OxNamedNode::new_unchecked("http://example.org/x");
864 let iri_s = IriS::from_named_node(&x);
865 let term = x.clone().into();
866 let mut parser = is_term(&term);
867 let result = parser.parse(&iri_s, graph);
868 assert!(result.is_ok())
869 }
870
871 #[test]
872 fn test_not() {
873 let graph = graph_from_str(DUMMY_GRAPH_9);
874 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
875 let q = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/q"));
876 assert!(not(property_value(&q)).parse(&x, graph).is_ok())
877 }
878
879 #[test]
880 fn test_iri() {
881 let graph = SRDFGraph::default();
882 let x = IriS::from_named_node(&OxNamedNode::new_unchecked("http://example.org/x"));
883 assert_eq!(iri().parse(&x, graph).unwrap(), x)
884 }
885
886 #[test]
887 fn test_add_triple_ref() {
888 let mut graph = SRDFGraph::default();
889 let s = OxNamedNode::new_unchecked("http://example.org/x");
890 let p = OxNamedNode::new_unchecked("http://example.org/p");
891 let o = OxNamedNode::new_unchecked("http://example.org/y");
892 graph.add_triple_ref(&s, &p, &o).unwrap();
893 assert_eq!(graph.len(), 1);
894 }
895}