#![allow(clippy::module_name_repetitions)]
use crate::literal::Literal;
use crate::DataType;
use rdftk_iri::{IRIRef, IRI};
use rdftk_names::rdf;
use std::fmt::{Display, Formatter};
use std::rc::Rc;
use unique_id::sequence::SequenceGenerator as IDGenerator;
use unique_id::Generator;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct SubjectNode {
inner: Subject,
}
pub type SubjectNodeRef = Rc<SubjectNode>;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ObjectNode {
inner: Object,
}
pub type ObjectNodeRef = Rc<ObjectNode>;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Statement {
subject: SubjectNodeRef,
predicate: IRIRef,
object: ObjectNodeRef,
}
pub type StatementRef = Rc<Statement>;
pub type StatementList = Vec<StatementRef>;
#[allow(clippy::upper_case_acronyms)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
enum Subject {
BNode(String),
IRI(IRIRef),
Star(StatementRef),
}
#[allow(clippy::upper_case_acronyms)]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
enum Object {
BNode(String),
IRI(IRIRef),
Literal(Literal),
Star(StatementRef),
}
impl Display for SubjectNode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match &self.inner {
Subject::BNode(node) => format!("_:{}", node),
Subject::IRI(iri) => format!("<{}>", iri),
Subject::Star(st) => format!("<{}>", st.to_string_no_dot()),
}
)
}
}
impl From<IRI> for SubjectNode {
fn from(iri: IRI) -> Self {
SubjectNode::named(iri.into())
}
}
impl From<IRIRef> for SubjectNode {
fn from(iri: IRIRef) -> Self {
SubjectNode::named(iri)
}
}
impl From<&IRIRef> for SubjectNode {
fn from(iri: &IRIRef) -> Self {
SubjectNode::named(iri.clone())
}
}
impl From<&StatementRef> for SubjectNode {
fn from(st: &StatementRef) -> Self {
SubjectNode::about(st.clone())
}
}
impl From<StatementRef> for SubjectNode {
fn from(st: StatementRef) -> Self {
SubjectNode::about(st)
}
}
impl SubjectNode {
pub fn blank() -> Self {
Self::blank_named(&new_blank_node_id())
}
pub fn blank_ref() -> SubjectNodeRef {
Rc::from(Self::blank())
}
pub fn blank_named(name: &str) -> Self {
Self {
inner: Subject::BNode(name.to_string()),
}
}
pub fn eq_blank(&self, other: &str) -> bool {
if let Some(value) = self.as_blank() {
value == other
} else {
false
}
}
pub fn named(name: IRIRef) -> Self {
Self {
inner: Subject::IRI(name),
}
}
pub fn named_ref(name: IRIRef) -> SubjectNodeRef {
Rc::from(Self::named(name))
}
pub fn eq_iri(&self, other: &IRIRef) -> bool {
if let Some(value) = self.as_iri() {
value == other
} else {
false
}
}
pub fn about(st: StatementRef) -> Self {
Self {
inner: Subject::Star(st),
}
}
pub fn about_ref(st: StatementRef) -> SubjectNodeRef {
Rc::from(Self::about(st))
}
pub fn eq_statement(&self, other: &StatementRef) -> bool {
if let Some(value) = self.as_statement() {
value == other
} else {
false
}
}
pub fn is_blank(&self) -> bool {
matches!(self.inner, Subject::BNode(_))
}
pub fn as_blank(&self) -> Option<&String> {
match &self.inner {
Subject::BNode(s) => Some(s),
_ => None,
}
}
pub fn is_iri(&self) -> bool {
matches!(self.inner, Subject::IRI(_))
}
#[inline]
pub fn is_named(&self) -> bool {
self.is_iri()
}
pub fn as_iri(&self) -> Option<&IRIRef> {
match &self.inner {
Subject::IRI(u) => Some(u),
_ => None,
}
}
pub fn is_statement(&self) -> bool {
matches!(self.inner, Subject::Star(_))
}
pub fn as_statement(&self) -> Option<&StatementRef> {
match &self.inner {
Subject::Star(st) => Some(st),
_ => None,
}
}
pub fn as_object(&self) -> ObjectNodeRef {
match &self.inner {
Subject::BNode(node) => ObjectNode::blank_named(node),
Subject::IRI(iri) => ObjectNode::named(iri.clone()),
Subject::Star(st) => ObjectNode::about(st.clone()),
}
.into()
}
}
impl Display for ObjectNode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match &self.inner {
Object::BNode(node) => format!("_:{}", node),
Object::IRI(iri) => format!("<{}>", iri),
Object::Literal(literal) => literal.to_string(),
Object::Star(st) => format!("<< {} >>", st.to_string_no_dot()),
}
)
}
}
impl From<IRI> for ObjectNode {
fn from(iri: IRI) -> Self {
ObjectNode::named(iri.into())
}
}
impl From<IRIRef> for ObjectNode {
fn from(iri: IRIRef) -> Self {
ObjectNode::named(iri)
}
}
impl From<&IRIRef> for ObjectNode {
fn from(iri: &IRIRef) -> Self {
ObjectNode::named(iri.clone())
}
}
impl From<Statement> for ObjectNodeRef {
fn from(st: Statement) -> Self {
ObjectNode::about_ref(Rc::from(st))
}
}
impl From<Literal> for ObjectNodeRef {
fn from(v: Literal) -> Self {
ObjectNode::literal_ref(v)
}
}
impl ObjectNode {
pub fn blank() -> Self {
Self::blank_named(&new_blank_node_id())
}
pub fn blank_ref() -> ObjectNodeRef {
Rc::from(Self::blank())
}
pub fn blank_named(name: &str) -> Self {
Self {
inner: Object::BNode(name.to_string()),
}
}
pub fn eq_blank(&self, other: &str) -> bool {
if let Some(value) = self.as_blank() {
value == other
} else {
false
}
}
pub fn named(name: IRIRef) -> Self {
Self {
inner: Object::IRI(name),
}
}
pub fn named_ref(name: IRIRef) -> ObjectNodeRef {
Rc::from(Self::named(name))
}
pub fn eq_iri(&self, other: &IRIRef) -> bool {
if let Some(value) = self.as_iri() {
value == other
} else {
false
}
}
pub fn literal(literal: Literal) -> Self {
Self {
inner: Object::Literal(literal),
}
}
pub fn literal_ref(literal: Literal) -> ObjectNodeRef {
Rc::from(Self::literal(literal))
}
pub fn literal_str(value: &str) -> Self {
Self::literal(Literal::new(value))
}
pub fn literal_with_type(value: &str, data_type: DataType) -> Self {
Self::literal(Literal::with_type(value, data_type))
}
pub fn literal_with_language(value: &str, language: &str) -> Self {
Self::literal(Literal::with_language(value, language))
}
pub fn eq_literal(&self, other: &Literal) -> bool {
if let Some(value) = self.as_literal() {
value == other
} else {
false
}
}
pub fn about(st: StatementRef) -> Self {
Self {
inner: Object::Star(st),
}
}
pub fn about_ref(st: StatementRef) -> ObjectNodeRef {
Rc::from(Self::about(st))
}
pub fn eq_statement(&self, other: &StatementRef) -> bool {
if let Some(value) = self.as_statement() {
value == other
} else {
false
}
}
pub fn is_blank(&self) -> bool {
matches!(self.inner, Object::BNode(_))
}
pub fn as_blank(&self) -> Option<&String> {
match &self.inner {
Object::BNode(s) => Some(s),
_ => None,
}
}
pub fn is_iri(&self) -> bool {
matches!(self.inner, Object::IRI(_))
}
pub fn as_iri(&self) -> Option<&IRIRef> {
match &self.inner {
Object::IRI(u) => Some(u),
_ => None,
}
}
pub fn is_literal(&self) -> bool {
matches!(self.inner, Object::Literal(_))
}
pub fn as_literal(&self) -> Option<&Literal> {
match &self.inner {
Object::Literal(l) => Some(l),
_ => None,
}
}
pub fn is_statement(&self) -> bool {
matches!(self.inner, Object::Star(_))
}
pub fn as_statement(&self) -> Option<&StatementRef> {
match &self.inner {
Object::Star(st) => Some(st),
_ => None,
}
}
pub fn as_subject(&self) -> Option<SubjectNode> {
match &self.inner {
Object::IRI(iri) => Some(SubjectNode::named(iri.clone())),
Object::BNode(b) => Some(SubjectNode::blank_named(b)),
Object::Star(st) => Some(SubjectNode::about(st.clone())),
_ => None,
}
}
}
impl Display for Statement {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{} .", &self.to_string_no_dot())
}
}
impl Statement {
pub fn new(subject: SubjectNodeRef, predicate: IRIRef, object: ObjectNodeRef) -> Self {
Self {
subject,
predicate,
object,
}
}
pub fn new_ref(
subject: SubjectNodeRef,
predicate: IRIRef,
object: ObjectNodeRef,
) -> StatementRef {
Rc::from(Self::new(subject, predicate, object))
}
pub fn also(&self, predicate: IRIRef, object: ObjectNodeRef) -> Self {
Self {
subject: self.subject.clone(),
predicate,
object,
}
}
pub fn about(&self, predicate: IRIRef, object: ObjectNodeRef) -> Self {
Self {
subject: SubjectNode::about(self.clone().into()).into(),
predicate,
object,
}
}
pub fn subject(&self) -> &SubjectNodeRef {
&self.subject
}
pub fn set_subject(&mut self, subject: SubjectNodeRef) {
self.subject = subject;
}
pub fn predicate(&self) -> &IRIRef {
&self.predicate
}
pub fn set_predicate(&mut self, predicate: IRIRef) {
self.predicate = predicate;
}
pub fn object(&self) -> &ObjectNodeRef {
&self.object
}
pub fn set_object(&mut self, object: ObjectNodeRef) {
self.object = object;
}
pub fn reify(&self) -> Vec<StatementRef> {
reify_statement(self).1
}
pub fn is_nested(&self) -> bool {
self.subject().is_statement() || self.object().is_statement()
}
pub fn to_string_no_dot(&self) -> String {
format!(
"{} <{}> {}",
&self.subject.to_string(),
&self.predicate.to_string(),
&self.object.to_string(),
)
}
}
fn new_blank_node_id() -> String {
format!("B{}", IDGenerator::default().next_id())
}
fn reify_statement(st: &Statement) -> (SubjectNodeRef, Vec<StatementRef>) {
let mut statements: Vec<StatementRef> = Default::default();
let new_subject = Rc::from(SubjectNode::blank());
statements.push(
Statement::new(
new_subject.clone(),
rdf::a_type().clone(),
ObjectNode::named(rdf::statement().clone()).into(),
)
.into(),
);
if st.subject().is_statement() {
let nested = reify_statement(st.subject().as_statement().unwrap());
statements.extend(nested.1);
statements.push(
Statement::new(
new_subject.clone(),
rdf::subject().clone(),
nested.0.as_object(),
)
.into(),
);
} else {
statements.push(
Statement::new(
new_subject.clone(),
rdf::subject().clone(),
st.subject().as_object(),
)
.into(),
);
}
statements.push(
Statement::new(
new_subject.clone(),
rdf::predicate().clone(),
ObjectNode::named(st.predicate().clone()).into(),
)
.into(),
);
if st.object().is_statement() {
let nested = reify_statement(st.object().as_statement().unwrap());
statements.extend(nested.1);
statements.push(
Statement::new(
new_subject.clone(),
rdf::object().clone(),
nested.0.as_object(),
)
.into(),
);
} else {
statements.push(
Statement::new(
new_subject.clone(),
rdf::object().clone(),
st.object().clone(),
)
.into(),
);
}
(new_subject, statements)
}