#![allow(clippy::module_name_repetitions)]
use crate::error::Result;
use crate::model::features::Featured;
use crate::model::features::FEATURE_RDF_STAR;
use rdftk_iri::Iri;
use rdftk_names::rdf;
use std::cmp::Ordering;
use std::fmt::Formatter;
use std::fmt::{Debug, Display};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Statement {
subject: SubjectNode,
predicate: Iri,
object: ObjectNode,
}
impl Display for Statement {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{} <{}> {}",
&self.subject().to_string(),
&self.predicate().to_string(),
&self.object().to_string(),
)
}
}
impl PartialOrd for Statement {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Statement {
fn cmp(&self, other: &Self) -> Ordering {
match self.subject.cmp(&other.subject) {
Ordering::Equal => {}
ord => return ord,
}
match self.predicate.cmp(&other.predicate) {
Ordering::Equal => {}
ord => return ord,
}
self.object.cmp(&other.object)
}
}
impl Featured for Statement {
fn supports_feature(&self, feature: &Iri) -> bool {
*feature == *FEATURE_RDF_STAR || *feature == *FEATURE_STMT_OBJECT_COLLECTIONS
}
}
impl Statement {
pub fn new<S, O>(subject: S, predicate: Iri, object: O) -> Self
where
S: Into<SubjectNode>,
O: Into<ObjectNode>,
{
Self {
subject: subject.into(),
predicate,
object: object.into(),
}
}
pub fn rdf_type<S, O>(subject: S, object: O) -> Self
where
S: Into<SubjectNode>,
O: Into<ObjectNode>,
{
Self::new(subject, rdf::a_type().clone(), object)
}
pub fn subject(&self) -> &SubjectNode {
&self.subject
}
pub fn set_subject(&mut self, subject: SubjectNode) {
self.subject = subject;
}
pub fn predicate(&self) -> &Iri {
&self.predicate
}
pub fn set_predicate(&mut self, predicate: Iri) {
self.predicate = predicate;
}
pub fn object(&self) -> &ObjectNode {
&self.object
}
pub fn set_object(&mut self, object: ObjectNode) {
self.object = object;
}
pub fn is_nested(&self) -> bool {
self.subject().is_statement() || self.object().is_statement()
}
pub fn reify(&self) -> Result<(SubjectNode, Vec<Self>)> {
let mut statements: Vec<Self> = Default::default();
let new_subject: SubjectNode = BlankNode::generate().into();
statements.push(Self::new(
new_subject.clone(),
rdf::a_type().clone(),
rdf::statement().clone(),
));
if let Some(statement) = self.subject().as_statement() {
let nested = statement.reify()?;
statements.extend(nested.1);
statements.push(Self::new(
new_subject.clone(),
rdf::subject().clone(),
nested.0.to_object(),
));
} else {
statements.push(Self::new(
new_subject.clone(),
rdf::subject().clone(),
self.subject().to_object(),
));
}
statements.push(Self::new(
new_subject.clone(),
rdf::predicate().clone(),
self.predicate().clone(),
));
if let Some(statement) = self.object().as_statement() {
let nested = statement.reify()?;
statements.extend(nested.1);
statements.push(Self::new(
new_subject.clone(),
rdf::object().clone(),
nested.0.to_object(),
));
} else {
statements.push(Self::new(
new_subject.clone(),
rdf::object().clone(),
self.object().clone(),
));
}
Ok((new_subject, statements))
}
}
mod bnode;
pub use bnode::*;
mod collection;
pub use collection::*;
mod subject;
pub use subject::*;
mod object;
pub use object::*;
use super::features::FEATURE_STMT_OBJECT_COLLECTIONS;