use crate::{
axioms::Declaration,
error::ApiError,
fmt::{DisplayPretty, Indenter},
ranges::HasArity,
syntax::{
ANONYMOUS_NAMESPACE, DELIM_ARGS_GROUP_START, DELIM_FN_ARGS_END, FN_ANNOTATION_PROPERTY,
FN_ANONYMOUS_INDIVIDUAL, FN_CLASS, FN_DATA_PROPERTY, FN_DATATYPE, FN_NAMED_INDIVIDUAL,
FN_OBJECT_PROPERTY, NAMESPACE_NAME_SEPARATOR,
},
values::UnlimitedNatural,
};
use core::{
fmt::{Display, Formatter, Result as FmtResult},
str::FromStr,
};
use rdftk_iri::{Iri, IriPrefixMap, Name};
use strum::{EnumIs, EnumTryAs};
#[cfg(not(feature = "std"))]
use alloc::{format, string::ToString};
#[derive(Clone, Debug, PartialEq, EnumIs, EnumTryAs)]
pub enum Entity {
AnnotationProperty(AnnotationProperty),
Class(Class),
DataProperty(DataProperty),
Datatype(Datatype),
ObjectProperty(ObjectProperty),
NamedIndividual(NamedIndividual),
}
#[derive(Clone, Debug, PartialEq)]
pub struct Class {
entity_iri: Iri,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Datatype {
entity_iri: Iri,
arity: UnlimitedNatural,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ObjectProperty {
entity_iri: Iri,
}
#[derive(Clone, Debug, PartialEq)]
pub struct DataProperty {
entity_iri: Iri,
}
#[derive(Clone, Debug, PartialEq)]
pub struct AnnotationProperty {
entity_iri: Iri,
}
#[derive(Clone, Debug, PartialEq, EnumIs, EnumTryAs)]
pub enum Individual {
NamedIndividual(NamedIndividual),
AnonymousIndividual(AnonymousIndividual),
}
#[derive(Clone, Debug, PartialEq)]
pub struct NamedIndividual {
entity_iri: Iri,
}
#[derive(Clone, Debug, PartialEq)]
pub struct AnonymousIndividual {
node_id: Name,
}
pub trait EntityTrait: DisplayPretty + From<Iri> + Into<Iri> {
fn new(entity_iri: Iri) -> Self;
fn entity_iri(&self) -> &Iri;
fn as_declaration(&self) -> Declaration;
}
pub trait IriAsEntity {
fn as_annotation_property(&self) -> AnnotationProperty;
fn as_class(&self) -> Class;
fn as_data_property(&self) -> DataProperty;
fn as_adatatype(&self) -> Datatype;
fn as_object_property(&self) -> ObjectProperty;
fn as_named_individual(&self) -> NamedIndividual;
}
macro_rules! impl_entity {
($type_name:ident) => {
impl ::core::fmt::Display for $type_name {
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
self.fmt_pretty(
f,
&crate::fmt::Indenter::default(),
&::rdftk_iri::map::IriPrefixMap::default(),
)
}
}
impl crate::fmt::DisplayPretty for $type_name {
fn fmt_pretty(
&self,
f: &mut ::core::fmt::Formatter<'_>,
indenter: &crate::fmt::Indenter,
prefix_map: &::rdftk_iri::map::IriPrefixMap,
) -> ::core::fmt::Result {
self.entity_iri.fmt_pretty(f, &indenter, prefix_map)
}
}
impl From<Iri> for $type_name {
fn from(entity_iri: Iri) -> Self {
Self { entity_iri }
}
}
impl From<&Iri> for $type_name {
fn from(entity_iri: &Iri) -> Self {
Self {
entity_iri: entity_iri.clone(),
}
}
}
impl From<$type_name> for Iri {
fn from(entity: $type_name) -> Iri {
entity.entity_iri
}
}
impl $crate::entities::EntityTrait for $type_name {
fn new(entity_iri: Iri) -> Self {
Self { entity_iri }
}
fn entity_iri(&self) -> &Iri {
&self.entity_iri
}
fn as_declaration(&self) -> Declaration {
Declaration::new(self.clone().into())
}
}
};
}
impl Display for Entity {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
self.fmt_pretty(f, &Indenter::default(), &IriPrefixMap::default())
}
}
impl DisplayPretty for Entity {
fn fmt_pretty(
&self,
f: &mut Formatter<'_>,
indenter: &Indenter,
prefix_map: &IriPrefixMap,
) -> FmtResult {
write!(
f,
"{}",
match self {
Self::AnnotationProperty(_) =>
format!("{FN_ANNOTATION_PROPERTY}{DELIM_ARGS_GROUP_START}"),
Self::Class(_) => format!("{FN_CLASS}{DELIM_ARGS_GROUP_START}"),
Self::DataProperty(_) => format!("{FN_DATA_PROPERTY}{DELIM_ARGS_GROUP_START}"),
Self::Datatype(_) => format!("{FN_DATATYPE}{DELIM_ARGS_GROUP_START}"),
Self::ObjectProperty(_) => format!("{FN_OBJECT_PROPERTY}{DELIM_ARGS_GROUP_START}"),
Self::NamedIndividual(_) =>
format!("{FN_NAMED_INDIVIDUAL}{DELIM_ARGS_GROUP_START}"),
}
)?;
if f.alternate() {
let _ = indenter.indent();
}
let entity_iri = match self {
Self::AnnotationProperty(v) => v.entity_iri(),
Self::Class(v) => v.entity_iri(),
Self::DataProperty(v) => v.entity_iri(),
Self::Datatype(v) => v.entity_iri(),
Self::ObjectProperty(v) => v.entity_iri(),
Self::NamedIndividual(v) => v.entity_iri(),
};
write!(f, "{}", indenter.separator_string(f.alternate()))?;
entity_iri.fmt_pretty(f, indenter, prefix_map)?;
if f.alternate() {
let _ = indenter.outdent();
}
write!(
f,
"{}{DELIM_FN_ARGS_END}",
indenter.separator_string(f.alternate())
)
}
}
impl From<AnnotationProperty> for Entity {
fn from(value: AnnotationProperty) -> Self {
Self::AnnotationProperty(value)
}
}
impl From<Class> for Entity {
fn from(value: Class) -> Self {
Self::Class(value)
}
}
impl From<DataProperty> for Entity {
fn from(value: DataProperty) -> Self {
Self::DataProperty(value)
}
}
impl From<Datatype> for Entity {
fn from(value: Datatype) -> Self {
Self::Datatype(value)
}
}
impl From<ObjectProperty> for Entity {
fn from(value: ObjectProperty) -> Self {
Self::ObjectProperty(value)
}
}
impl From<NamedIndividual> for Entity {
fn from(value: NamedIndividual) -> Self {
Self::NamedIndividual(value)
}
}
impl Entity {
pub fn entity_iri(&self) -> &Iri {
match self {
Entity::AnnotationProperty(annotation_property) => annotation_property.entity_iri(),
Entity::Class(class) => class.entity_iri(),
Entity::DataProperty(data_property) => data_property.entity_iri(),
Entity::Datatype(datatype) => datatype.entity_iri(),
Entity::ObjectProperty(object_property) => object_property.entity_iri(),
Entity::NamedIndividual(named_individual) => named_individual.entity_iri(),
}
}
pub fn as_declaration(&self) -> Declaration {
Declaration::new(self.clone())
}
}
impl_entity!(AnnotationProperty);
impl_entity!(Class);
impl_entity!(DataProperty);
impl_display_pretty!(Datatype(entity_iri));
impl HasArity for Datatype {
fn arity(&self) -> UnlimitedNatural {
self.arity
}
}
impl From<Iri> for Datatype {
fn from(entity_iri: Iri) -> Datatype {
Self::new(entity_iri)
}
}
impl Datatype {
pub fn new(entity_iri: Iri) -> Self {
Self {
entity_iri,
arity: UnlimitedNatural::Limited(1), }
}
pub fn entity_iri(&self) -> &Iri {
&self.entity_iri
}
pub fn as_declaration(&self) -> Declaration {
Declaration::new(self.clone().into())
}
}
impl_entity!(ObjectProperty);
impl_display_pretty!(Individual enum NamedIndividual, AnonymousIndividual);
impl_entity!(NamedIndividual);
impl Display for AnonymousIndividual {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
self.fmt_pretty(f, &Indenter::default(), &IriPrefixMap::default())
}
}
impl DisplayPretty for AnonymousIndividual {
fn fmt_pretty(&self, f: &mut Formatter<'_>, _: &Indenter, _: &IriPrefixMap) -> FmtResult {
write!(
f,
"{ANONYMOUS_NAMESPACE}{NAMESPACE_NAME_SEPARATOR}{}",
self.node_id
)
}
}
impl FromStr for AnonymousIndividual {
type Err = ApiError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self {
node_id: Name::from_str(s).map_err(|e| {
ApiError::ValueParser(FN_ANONYMOUS_INDIVIDUAL, e.to_string(), s.to_string())
})?,
})
}
}
impl From<Name> for AnonymousIndividual {
fn from(node_id: Name) -> Self {
Self { node_id }
}
}
impl AnonymousIndividual {
pub fn node_id(&self) -> &Name {
&self.node_id
}
}
impl IriAsEntity for Iri {
fn as_annotation_property(&self) -> AnnotationProperty {
AnnotationProperty::new(self.clone())
}
fn as_class(&self) -> Class {
Class::new(self.clone())
}
fn as_data_property(&self) -> DataProperty {
DataProperty::new(self.clone())
}
fn as_adatatype(&self) -> Datatype {
Datatype::new(self.clone())
}
fn as_object_property(&self) -> ObjectProperty {
ObjectProperty::new(self.clone())
}
fn as_named_individual(&self) -> NamedIndividual {
NamedIndividual::new(self.clone())
}
}