use std::sync::Arc;
use serde::{Deserialize, Serialize};
use crate::attribute::ValueType;
use crate::entity::Annotation;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct OwnedAttributeDescriptor {
pub field_name: String,
pub attr_name: String,
pub value_type: ValueType,
pub annotations: Vec<Annotation>,
pub is_optional: bool,
#[serde(default)]
pub is_ordered: bool,
}
impl OwnedAttributeDescriptor {
pub fn is_key(&self) -> bool {
self.annotations
.iter()
.any(|annotation| matches!(annotation, Annotation::Key))
}
pub fn is_unique(&self) -> bool {
self.annotations
.iter()
.any(|annotation| matches!(annotation, Annotation::Unique))
}
pub fn cardinality(&self) -> Option<(u32, Option<u32>)> {
self.annotations
.iter()
.find_map(|annotation| match annotation {
Annotation::Card(min, max) => Some((*min, *max)),
_ => None,
})
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct RoleDescriptor {
pub role_name: String,
pub player_type_names: Vec<String>,
pub cardinality: Option<(u32, Option<u32>)>,
pub overrides: Option<String>,
#[serde(default)]
pub is_abstract: bool,
#[serde(default)]
pub ordered: bool,
#[serde(default)]
pub distinct: bool,
#[serde(default)]
pub plays_cardinality: Option<(u32, Option<u32>)>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct EntityDescriptor {
pub type_name: String,
pub is_abstract: bool,
pub parent_type: Option<String>,
pub owned_attributes: Vec<OwnedAttributeDescriptor>,
}
impl EntityDescriptor {
pub fn key_attribute(&self) -> Option<&OwnedAttributeDescriptor> {
self.owned_attributes.iter().find(|attr| attr.is_key())
}
pub fn attribute(&self, name: &str) -> Option<&OwnedAttributeDescriptor> {
self.owned_attributes
.iter()
.find(|attr| attr.field_name == name || attr.attr_name == name)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct RelationDescriptor {
pub type_name: String,
pub is_abstract: bool,
pub parent_type: Option<String>,
pub owned_attributes: Vec<OwnedAttributeDescriptor>,
pub roles: Vec<RoleDescriptor>,
}
impl RelationDescriptor {
pub fn key_attribute(&self) -> Option<&OwnedAttributeDescriptor> {
self.owned_attributes.iter().find(|attr| attr.is_key())
}
pub fn attribute(&self, name: &str) -> Option<&OwnedAttributeDescriptor> {
self.owned_attributes
.iter()
.find(|attr| attr.field_name == name || attr.attr_name == name)
}
pub fn role(&self, name: &str) -> Option<&RoleDescriptor> {
self.roles.iter().find(|role| role.role_name == name)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", content = "descriptor", rename_all = "snake_case")]
pub enum TypeDescriptor {
Entity(EntityDescriptor),
Relation(RelationDescriptor),
}
impl TypeDescriptor {
pub fn type_name(&self) -> &str {
match self {
Self::Entity(descriptor) => &descriptor.type_name,
Self::Relation(descriptor) => &descriptor.type_name,
}
}
}
#[derive(Debug, Clone)]
pub enum TypeDescriptorRef {
Entity(Arc<EntityDescriptor>),
Relation(Arc<RelationDescriptor>),
}
impl TypeDescriptorRef {
pub fn type_name(&self) -> &str {
match self {
Self::Entity(descriptor) => &descriptor.type_name,
Self::Relation(descriptor) => &descriptor.type_name,
}
}
pub fn to_owned_descriptor(&self) -> TypeDescriptor {
match self {
Self::Entity(descriptor) => TypeDescriptor::Entity((**descriptor).clone()),
Self::Relation(descriptor) => TypeDescriptor::Relation((**descriptor).clone()),
}
}
}