Adds RDF-star support to formatters

Looses nice formatting for Turtle and TriG waiting for a better model
pull/171/head
Tpt 3 years ago
parent f3eeecb08d
commit 18e1e03f0f
  1. 169
      lib/src/io/write.rs
  2. 10
      lib/src/model/triple.rs

@ -3,9 +3,8 @@
use crate::error::invalid_input_error; use crate::error::invalid_input_error;
use crate::io::{DatasetFormat, GraphFormat}; use crate::io::{DatasetFormat, GraphFormat};
use crate::model::*; use crate::model::*;
use rio_api::formatter::{QuadsFormatter, TriplesFormatter}; use rio_api::formatter::TriplesFormatter;
use rio_api::model as rio; use rio_api::model as rio;
use rio_turtle::{NQuadsFormatter, NTriplesFormatter, TriGFormatter, TurtleFormatter};
use rio_xml::RdfXmlFormatter; use rio_xml::RdfXmlFormatter;
use std::io; use std::io;
use std::io::Write; use std::io::Write;
@ -48,8 +47,7 @@ impl GraphSerializer {
pub fn triple_writer<W: Write>(&self, writer: W) -> io::Result<TripleWriter<W>> { pub fn triple_writer<W: Write>(&self, writer: W) -> io::Result<TripleWriter<W>> {
Ok(TripleWriter { Ok(TripleWriter {
formatter: match self.format { formatter: match self.format {
GraphFormat::NTriples => TripleWriterKind::NTriples(NTriplesFormatter::new(writer)), GraphFormat::NTriples | GraphFormat::Turtle => TripleWriterKind::NTriples(writer),
GraphFormat::Turtle => TripleWriterKind::Turtle(TurtleFormatter::new(writer)),
GraphFormat::RdfXml => TripleWriterKind::RdfXml(RdfXmlFormatter::new(writer)?), GraphFormat::RdfXml => TripleWriterKind::RdfXml(RdfXmlFormatter::new(writer)?),
}, },
}) })
@ -83,8 +81,7 @@ pub struct TripleWriter<W: Write> {
} }
enum TripleWriterKind<W: Write> { enum TripleWriterKind<W: Write> {
NTriples(NTriplesFormatter<W>), NTriples(W),
Turtle(TurtleFormatter<W>),
RdfXml(RdfXmlFormatter<W>), RdfXml(RdfXmlFormatter<W>),
} }
@ -92,53 +89,49 @@ impl<W: Write> TripleWriter<W> {
/// Writes a triple /// Writes a triple
pub fn write<'a>(&mut self, triple: impl Into<TripleRef<'a>>) -> io::Result<()> { pub fn write<'a>(&mut self, triple: impl Into<TripleRef<'a>>) -> io::Result<()> {
let triple = triple.into(); let triple = triple.into();
let triple = rio::Triple { match &mut self.formatter {
subject: match triple.subject { TripleWriterKind::NTriples(writer) => {
SubjectRef::NamedNode(node) => rio::NamedNode { iri: node.as_str() }.into(), writeln!(writer, "{} .", triple)?;
SubjectRef::BlankNode(node) => rio::BlankNode { id: node.as_str() }.into(), }
SubjectRef::Triple(_) => { TripleWriterKind::RdfXml(formatter) => formatter.format(&rio::Triple {
return Err(invalid_input_error( subject: match triple.subject {
"Rio library does not support RDF-star yet", SubjectRef::NamedNode(node) => rio::NamedNode { iri: node.as_str() }.into(),
)) SubjectRef::BlankNode(node) => rio::BlankNode { id: node.as_str() }.into(),
} SubjectRef::Triple(_) => {
}, return Err(invalid_input_error("RDF/XML does not support RDF-star yet"))
predicate: rio::NamedNode { }
iri: triple.predicate.as_str(), },
}, predicate: rio::NamedNode {
object: match triple.object { iri: triple.predicate.as_str(),
TermRef::NamedNode(node) => rio::NamedNode { iri: node.as_str() }.into(), },
TermRef::BlankNode(node) => rio::BlankNode { id: node.as_str() }.into(), object: match triple.object {
TermRef::Literal(literal) => if literal.is_plain() { TermRef::NamedNode(node) => rio::NamedNode { iri: node.as_str() }.into(),
if let Some(language) = literal.language() { TermRef::BlankNode(node) => rio::BlankNode { id: node.as_str() }.into(),
rio::Literal::LanguageTaggedString { TermRef::Literal(literal) => if literal.is_plain() {
value: literal.value(), if let Some(language) = literal.language() {
language, rio::Literal::LanguageTaggedString {
value: literal.value(),
language,
}
} else {
rio::Literal::Simple {
value: literal.value(),
}
} }
} else { } else {
rio::Literal::Simple { rio::Literal::Typed {
value: literal.value(), value: literal.value(),
datatype: rio::NamedNode {
iri: literal.datatype().as_str(),
},
} }
} }
} else { .into(),
rio::Literal::Typed { TermRef::Triple(_) => {
value: literal.value(), return Err(invalid_input_error("RDF/XML does not support RDF-star yet"))
datatype: rio::NamedNode {
iri: literal.datatype().as_str(),
},
} }
} },
.into(), })?,
TermRef::Triple(_) => {
return Err(invalid_input_error(
"Rio library does not support RDF-star yet",
))
}
},
};
match &mut self.formatter {
TripleWriterKind::NTriples(formatter) => formatter.format(&triple)?,
TripleWriterKind::Turtle(formatter) => formatter.format(&triple)?,
TripleWriterKind::RdfXml(formatter) => formatter.format(&triple)?,
} }
Ok(()) Ok(())
} }
@ -146,9 +139,10 @@ impl<W: Write> TripleWriter<W> {
/// Writes the last bytes of the file /// Writes the last bytes of the file
pub fn finish(self) -> io::Result<()> { pub fn finish(self) -> io::Result<()> {
match self.formatter { match self.formatter {
TripleWriterKind::NTriples(formatter) => formatter.finish(), TripleWriterKind::NTriples(_) => (),
TripleWriterKind::Turtle(formatter) => formatter.finish()?, TripleWriterKind::RdfXml(formatter) => {
TripleWriterKind::RdfXml(formatter) => formatter.finish()?, formatter.finish()?;
}
}; };
Ok(()) Ok(())
} }
@ -192,8 +186,8 @@ impl DatasetSerializer {
pub fn quad_writer<W: Write>(&self, writer: W) -> io::Result<QuadWriter<W>> { pub fn quad_writer<W: Write>(&self, writer: W) -> io::Result<QuadWriter<W>> {
Ok(QuadWriter { Ok(QuadWriter {
formatter: match self.format { formatter: match self.format {
DatasetFormat::NQuads => QuadWriterKind::NQuads(NQuadsFormatter::new(writer)), DatasetFormat::NQuads => QuadWriterKind::NQuads(writer),
DatasetFormat::TriG => QuadWriterKind::TriG(TriGFormatter::new(writer)), DatasetFormat::TriG => QuadWriterKind::TriG(writer),
}, },
}) })
} }
@ -227,75 +221,36 @@ pub struct QuadWriter<W: Write> {
} }
enum QuadWriterKind<W: Write> { enum QuadWriterKind<W: Write> {
NQuads(NQuadsFormatter<W>), NQuads(W),
TriG(TriGFormatter<W>), TriG(W),
} }
impl<W: Write> QuadWriter<W> { impl<W: Write> QuadWriter<W> {
/// Writes a quad /// Writes a quad
pub fn write<'a>(&mut self, quad: impl Into<QuadRef<'a>>) -> io::Result<()> { pub fn write<'a>(&mut self, quad: impl Into<QuadRef<'a>>) -> io::Result<()> {
let quad = quad.into(); let quad = quad.into();
let quad = rio::Quad { match &mut self.formatter {
subject: match quad.subject { QuadWriterKind::NQuads(writer) => {
SubjectRef::NamedNode(node) => rio::NamedNode { iri: node.as_str() }.into(), writeln!(writer, "{} .", quad)?;
SubjectRef::BlankNode(node) => rio::BlankNode { id: node.as_str() }.into(), }
SubjectRef::Triple(_) => { QuadWriterKind::TriG(writer) => {
return Err(invalid_input_error( if quad.graph_name == GraphNameRef::DefaultGraph {
"Rio library does not support RDF-star yet", writeln!(
)) writer,
} "GRAPH {} {{ {} }}",
}, quad.graph_name,
predicate: rio::NamedNode { TripleRef::from(quad)
iri: quad.predicate.as_str(), )?;
},
object: match quad.object {
TermRef::NamedNode(node) => rio::NamedNode { iri: node.as_str() }.into(),
TermRef::BlankNode(node) => rio::BlankNode { id: node.as_str() }.into(),
TermRef::Literal(literal) => if literal.is_plain() {
if let Some(language) = literal.language() {
rio::Literal::LanguageTaggedString {
value: literal.value(),
language,
}
} else {
rio::Literal::Simple {
value: literal.value(),
}
}
} else { } else {
rio::Literal::Typed { writeln!(writer, "{} .", quad)?;
value: literal.value(),
datatype: rio::NamedNode {
iri: literal.datatype().as_str(),
},
}
} }
.into(), }
TermRef::Triple(_) => {
return Err(invalid_input_error(
"Rio library does not support RDF-star yet",
))
}
},
graph_name: match quad.graph_name {
GraphNameRef::NamedNode(node) => Some(rio::NamedNode { iri: node.as_str() }.into()),
GraphNameRef::BlankNode(node) => Some(rio::BlankNode { id: node.as_str() }.into()),
GraphNameRef::DefaultGraph => None,
},
};
match &mut self.formatter {
QuadWriterKind::NQuads(formatter) => formatter.format(&quad)?,
QuadWriterKind::TriG(formatter) => formatter.format(&quad)?,
} }
Ok(()) Ok(())
} }
/// Writes the last bytes of the file /// Writes the last bytes of the file
pub fn finish(self) -> io::Result<()> { pub fn finish(self) -> io::Result<()> {
match self.formatter {
QuadWriterKind::NQuads(formatter) => formatter.finish(),
QuadWriterKind::TriG(formatter) => formatter.finish()?,
};
Ok(()) Ok(())
} }
} }

@ -1078,7 +1078,15 @@ impl<'a> QuadRef<'a> {
impl fmt::Display for QuadRef<'_> { impl fmt::Display for QuadRef<'_> {
#[inline] #[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} {} {}", self.subject, self.predicate, self.object) if self.graph_name == GraphNameRef::DefaultGraph {
write!(f, "{} {} {}", self.subject, self.predicate, self.object)
} else {
write!(
f,
"{} {} {} {}",
self.subject, self.predicate, self.object, self.graph_name
)
}
} }
} }

Loading…
Cancel
Save