use std::fmt;
use chrono::{DateTime, NaiveDate, NaiveDateTime};
pub use self::{
instance::{Attribute, Entity, Relation},
type_::{AttributeType, EntityType, RelationType, RoleType},
value::{Value, ValueType},
};
use crate::{
IID,
concept::value::{Decimal, Duration, Struct, TimeZone},
};
pub mod instance;
pub mod type_;
pub mod value;
#[derive(Clone, PartialEq)]
pub enum Concept {
EntityType(EntityType),
RelationType(RelationType),
RoleType(RoleType),
AttributeType(AttributeType),
Entity(Entity),
Relation(Relation),
Attribute(Attribute),
Value(Value),
}
#[derive(Clone, PartialEq)]
pub enum ConceptCategory {
EntityType,
RelationType,
RoleType,
AttributeType,
Entity,
Relation,
Attribute,
Value,
}
impl ConceptCategory {
pub const fn name(&self) -> &'static str {
match self {
ConceptCategory::EntityType => "EntityType",
ConceptCategory::RelationType => "RelationType",
ConceptCategory::RoleType => "RoleType",
ConceptCategory::AttributeType => "AttributeType",
ConceptCategory::Entity => "Entity",
ConceptCategory::Relation => "Relation",
ConceptCategory::Attribute => "Attribute",
ConceptCategory::Value => "Value",
}
}
}
impl fmt::Display for ConceptCategory {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl fmt::Debug for ConceptCategory {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}
impl Concept {
pub(crate) const UNKNOWN_LABEL: &'static str = "unknown";
pub fn try_get_iid(&self) -> Option<&IID> {
match self {
Self::Entity(entity) => Some(&entity.iid),
Self::Relation(relation) => Some(&relation.iid),
_ => None,
}
}
pub fn get_label(&self) -> &str {
self.try_get_label().unwrap_or(Self::UNKNOWN_LABEL)
}
pub fn try_get_label(&self) -> Option<&str> {
match self {
Self::EntityType(entity_type) => Some(entity_type.label()),
Self::RelationType(relation_type) => Some(relation_type.label()),
Self::AttributeType(attribute_type) => Some(attribute_type.label()),
Self::RoleType(role_type) => Some(role_type.label()),
Self::Entity(entity) => entity.type_().map(|type_| type_.label()),
Self::Relation(relation) => relation.type_().map(|type_| type_.label()),
Self::Attribute(attribute) => attribute.type_().map(|type_| type_.label()),
Self::Value(value) => Some(value.get_type_name()),
}
}
pub fn try_get_value_label(&self) -> Option<&str> {
match self {
Self::AttributeType(attribute_type) => attribute_type.value_type().map(|value_type| value_type.name()),
Self::Attribute(attribute) => Some(attribute.value.get_type_name()),
Self::Value(value) => Some(value.get_type_name()),
_ => None,
}
}
pub fn try_get_value_type(&self) -> Option<ValueType> {
match self {
Self::AttributeType(attribute_type) => attribute_type.value_type().cloned(),
Self::Attribute(attribute) => Some(attribute.value.get_type()),
Self::Value(value) => Some(value.get_type()),
_ => None,
}
}
pub fn try_get_value(&self) -> Option<&Value> {
match self {
Self::Attribute(attribute) => Some(&attribute.value),
Self::Value(value) => Some(value),
_ => None,
}
}
pub fn try_get_boolean(&self) -> Option<bool> {
self.try_get_value().and_then(|value| value.get_boolean())
}
pub fn try_get_integer(&self) -> Option<i64> {
self.try_get_value().and_then(|value| value.get_integer())
}
pub fn try_get_double(&self) -> Option<f64> {
self.try_get_value().and_then(|value| value.get_double())
}
pub fn try_get_decimal(&self) -> Option<Decimal> {
self.try_get_value().and_then(|value| value.get_decimal())
}
pub fn try_get_string(&self) -> Option<&str> {
self.try_get_value().and_then(|value| value.get_string())
}
pub fn try_get_date(&self) -> Option<NaiveDate> {
self.try_get_value().and_then(|value| value.get_date())
}
pub fn try_get_datetime(&self) -> Option<NaiveDateTime> {
self.try_get_value().and_then(|value| value.get_datetime())
}
pub fn try_get_datetime_tz(&self) -> Option<DateTime<TimeZone>> {
self.try_get_value().and_then(|value| value.get_datetime_tz())
}
pub fn try_get_duration(&self) -> Option<Duration> {
self.try_get_value().and_then(|value| value.get_duration())
}
pub fn try_get_struct(&self) -> Option<&Struct> {
self.try_get_value().and_then(|value| value.get_struct())
}
pub fn get_category(&self) -> ConceptCategory {
match self {
Self::EntityType(_) => ConceptCategory::EntityType,
Self::RelationType(_) => ConceptCategory::RelationType,
Self::RoleType(_) => ConceptCategory::RoleType,
Self::AttributeType(_) => ConceptCategory::AttributeType,
Self::Entity(_) => ConceptCategory::Entity,
Self::Relation(_) => ConceptCategory::Relation,
Self::Attribute(_) => ConceptCategory::Attribute,
Self::Value(_) => ConceptCategory::Value,
}
}
pub fn is_type(&self) -> bool {
matches!(self, Self::EntityType(_) | Self::RelationType(_) | Self::RoleType(_) | Self::AttributeType(_))
}
pub fn is_entity_type(&self) -> bool {
matches!(self.get_category(), ConceptCategory::EntityType)
}
pub fn is_relation_type(&self) -> bool {
matches!(self.get_category(), ConceptCategory::RelationType)
}
pub fn is_role_type(&self) -> bool {
matches!(self.get_category(), ConceptCategory::RoleType)
}
pub fn is_attribute_type(&self) -> bool {
matches!(self.get_category(), ConceptCategory::AttributeType)
}
pub fn is_instance(&self) -> bool {
matches!(self, Self::Entity(_) | Self::Relation(_) | Self::Attribute(_))
}
pub fn is_entity(&self) -> bool {
matches!(self.get_category(), ConceptCategory::Entity)
}
pub fn is_relation(&self) -> bool {
matches!(self.get_category(), ConceptCategory::Relation)
}
pub fn is_attribute(&self) -> bool {
matches!(self.get_category(), ConceptCategory::Attribute)
}
pub fn is_value(&self) -> bool {
matches!(self.get_category(), ConceptCategory::Value)
}
pub fn is_boolean(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::Boolean))
}
pub fn is_integer(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::Integer))
}
pub fn is_decimal(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::Decimal))
}
pub fn is_double(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::Double))
}
pub fn is_string(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::String))
}
pub fn is_date(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::Date))
}
pub fn is_datetime(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::Datetime))
}
pub fn is_datetime_tz(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::DatetimeTZ))
}
pub fn is_duration(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::Duration))
}
pub fn is_struct(&self) -> bool {
matches!(self.try_get_value_type(), Some(ValueType::Struct(_)))
}
}
impl fmt::Display for Concept {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(self, f)
}
}
impl fmt::Debug for Concept {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_type() {
write!(f, "{}({})", self.get_category(), self.get_label())
} else {
write!(f, "{}({}", self.get_category(), self.get_label())?;
if self.try_get_iid().is_some() {
write!(f, ": {}", self.try_get_iid().unwrap())?;
if self.try_get_value().is_some() {
write!(f, ", {}", self.try_get_value().unwrap())?;
}
} else if self.try_get_value().is_some() {
write!(f, ": {}", self.try_get_value().unwrap())?;
} else {
}
write!(f, ")")
}
}
}
#[repr(C)]
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub enum Kind {
Entity,
Attribute,
Relation,
Role,
}
impl Kind {
pub const fn name(&self) -> &'static str {
match self {
Kind::Entity => "entity",
Kind::Attribute => "attribute",
Kind::Relation => "relation",
Kind::Role => "relation:role",
}
}
}
impl fmt::Debug for Kind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Kind[{}]", self.name())
}
}
impl fmt::Display for Kind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}