use crate::model::features::{Featured, FEATURE_RDF_STAR, FEATURE_STMT_OBJECT_COLLECTIONS};
use crate::model::literal::Literal;
use crate::model::statement::{
BlankNode, Collection, Statement, SubjectNode, BLANK_NODE_NAMESPACE,
};
use rdftk_iri::{Iri, Name};
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::fmt::{Debug, Display, Formatter};
use std::sync::Arc;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ObjectNode {
Blank(BlankNode),
Resource(Iri),
Literal(Literal),
Collection(Collection),
Statement(Arc<Statement>),
}
impl From<&ObjectNode> for ObjectNode {
fn from(v: &ObjectNode) -> Self {
v.clone()
}
}
impl From<BlankNode> for ObjectNode {
fn from(v: BlankNode) -> Self {
Self::Blank(v)
}
}
impl From<&BlankNode> for ObjectNode {
fn from(v: &BlankNode) -> Self {
Self::Blank(v.clone())
}
}
impl From<Name> for ObjectNode {
fn from(v: Name) -> Self {
Self::Blank(v.into())
}
}
impl From<&Name> for ObjectNode {
fn from(v: &Name) -> Self {
Self::Blank(v.clone().into())
}
}
impl From<Iri> for ObjectNode {
fn from(v: Iri) -> Self {
Self::Resource(v)
}
}
impl From<&Iri> for ObjectNode {
fn from(v: &Iri) -> Self {
Self::Resource(v.clone())
}
}
impl From<Literal> for ObjectNode {
fn from(v: Literal) -> Self {
Self::Literal(v)
}
}
impl From<&Literal> for ObjectNode {
fn from(v: &Literal) -> Self {
Self::Literal(v.clone())
}
}
impl From<Collection> for ObjectNode {
fn from(v: Collection) -> Self {
Self::Collection(v)
}
}
impl From<&Collection> for ObjectNode {
fn from(v: &Collection) -> Self {
Self::Collection(v.clone())
}
}
impl From<Statement> for ObjectNode {
fn from(v: Statement) -> Self {
Self::Statement(Arc::new(v))
}
}
impl From<&Statement> for ObjectNode {
fn from(v: &Statement) -> Self {
Self::Statement(Arc::new(v.clone()))
}
}
impl From<Arc<Statement>> for ObjectNode {
fn from(v: Arc<Statement>) -> Self {
Self::Statement(v)
}
}
impl From<&Arc<Statement>> for ObjectNode {
fn from(v: &Arc<Statement>) -> Self {
Self::Statement(v.clone())
}
}
impl Display for ObjectNode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Blank(node) => write!(f, "{}:{}", BLANK_NODE_NAMESPACE, node),
Self::Resource(iri) => write!(f, "<{}>", iri),
Self::Literal(lit) => write!(f, "{}", lit),
Self::Collection(col) => write!(f, "{}", col),
Self::Statement(st) => write!(f, "<< {} >>", st),
}
}
}
impl PartialEq<BlankNode> for ObjectNode {
fn eq(&self, other: &BlankNode) -> bool {
match self {
Self::Blank(value) => value == other,
_ => false,
}
}
}
impl PartialEq<Iri> for ObjectNode {
fn eq(&self, other: &Iri) -> bool {
match self {
Self::Resource(value) => value == other,
_ => false,
}
}
}
impl PartialEq<Literal> for ObjectNode {
fn eq(&self, other: &Literal) -> bool {
match self {
Self::Literal(value) => value == other,
_ => false,
}
}
}
impl PartialEq<Collection> for ObjectNode {
fn eq(&self, other: &Collection) -> bool {
match self {
Self::Collection(value) => value == other,
_ => false,
}
}
}
impl PartialEq<Statement> for ObjectNode {
fn eq(&self, other: &Statement) -> bool {
match self {
Self::Statement(value) => {
<Arc<Statement> as Borrow<Statement>>::borrow(value) == other.borrow()
}
_ => false,
}
}
}
impl PartialEq<Arc<Statement>> for ObjectNode {
fn eq(&self, other: &Arc<Statement>) -> bool {
match self {
Self::Statement(value) => value == other,
_ => false,
}
}
}
impl PartialOrd for ObjectNode {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ObjectNode {
fn cmp(&self, other: &Self) -> Ordering {
match (self, other) {
(Self::Blank(lhs), Self::Blank(rhs)) => lhs.cmp(rhs),
(Self::Blank(_), Self::Resource(_)) => Ordering::Less,
(Self::Blank(_), Self::Literal(_)) => Ordering::Less,
(Self::Blank(_), Self::Collection(_)) => Ordering::Less,
(Self::Blank(_), Self::Statement(_)) => Ordering::Less,
(Self::Resource(_), Self::Blank(_)) => Ordering::Greater,
(Self::Resource(lhs), Self::Resource(rhs)) => lhs.cmp(rhs),
(Self::Resource(_), Self::Literal(_)) => Ordering::Less,
(Self::Resource(_), Self::Collection(_)) => Ordering::Less,
(Self::Resource(_), Self::Statement(_)) => Ordering::Less,
(Self::Literal(_), Self::Blank(_)) => Ordering::Greater,
(Self::Literal(_), Self::Resource(_)) => Ordering::Greater,
(Self::Literal(lhs), Self::Literal(rhs)) => lhs.cmp(rhs),
(Self::Literal(_), Self::Collection(_)) => Ordering::Less,
(Self::Literal(_), Self::Statement(_)) => Ordering::Less,
(Self::Collection(_), Self::Blank(_)) => Ordering::Greater,
(Self::Collection(_), Self::Resource(_)) => Ordering::Greater,
(Self::Collection(_), Self::Literal(_)) => Ordering::Greater,
(Self::Collection(lhs), Self::Collection(rhs)) => lhs.cmp(rhs),
(Self::Collection(_), Self::Statement(_)) => Ordering::Less,
(Self::Statement(_), Self::Blank(_)) => Ordering::Greater,
(Self::Statement(_), Self::Resource(_)) => Ordering::Greater,
(Self::Statement(_), Self::Literal(_)) => Ordering::Greater,
(Self::Statement(_), Self::Collection(_)) => Ordering::Greater,
(Self::Statement(lhs), Self::Statement(rhs)) => lhs.cmp(rhs),
}
}
}
impl Featured for ObjectNode {
fn supports_feature(&self, feature: &Iri) -> bool {
*feature == *FEATURE_RDF_STAR || *feature == *FEATURE_STMT_OBJECT_COLLECTIONS
}
}
impl ObjectNode {
pub fn is_blank(&self) -> bool {
matches!(self, Self::Blank(_))
}
pub fn as_blank(&self) -> Option<&BlankNode> {
match &self {
Self::Blank(v) => Some(v),
_ => None,
}
}
pub fn is_resource(&self) -> bool {
matches!(self, Self::Resource(_))
}
pub fn as_resource(&self) -> Option<&Iri> {
match &self {
Self::Resource(v) => Some(v),
_ => None,
}
}
pub fn is_literal(&self) -> bool {
matches!(self, Self::Literal(_))
}
pub fn as_literal(&self) -> Option<&Literal> {
match &self {
Self::Literal(v) => Some(v),
_ => None,
}
}
pub fn is_collection(&self) -> bool {
matches!(self, Self::Collection(_))
}
pub fn as_collection(&self) -> Option<&Collection> {
match &self {
Self::Collection(v) => Some(v),
_ => None,
}
}
pub fn is_statement(&self) -> bool {
matches!(self, Self::Statement(_))
}
pub fn as_statement(&self) -> Option<Arc<Statement>> {
match &self {
Self::Statement(v) => Some(v.clone()),
_ => None,
}
}
pub fn to_subject(&self) -> Option<SubjectNode> {
match self {
ObjectNode::Blank(v) => Some(v.clone().into()),
ObjectNode::Resource(v) => Some(v.clone().into()),
ObjectNode::Statement(v) => Some(v.clone().into()),
ObjectNode::Literal(_) => None,
ObjectNode::Collection(_) => None,
}
}
}