use super::common::{Document, DocumentReference, I18NString, Translatable};
use crate::structure::translation::TranslationDocument;
use jsonapi::model::*;
pub type DomainDocument = Document<Domain>;
jsonapi_model!(DomainDocument; "domain");
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct Domain {
pub events: Events,
pub entities: Entities,
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct Events {
pub change: Vec<DocumentReference>,
pub update: Vec<DocumentReference>,
pub read: Vec<DocumentReference>,
pub delete: Vec<DocumentReference>,
pub all: Vec<DocumentReference>,
}
pub type Entities = Vec<Entity>;
pub type Attributes = Vec<Attribute>;
pub type References = Vec<Reference>;
pub type Validations = Vec<Validation>;
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct Validation {
pub message: I18NString,
pub xflow: DocumentReference,
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct Attribute {
pub name: String,
pub vtype: String,
pub default: String,
pub validations: Vec<Validation>,
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub enum ReferenceType {
#[serde(rename = "has_many")]
HasMany,
#[serde(rename = "belongs_to")]
BelongsTo,
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct Reference {
pub name: String,
pub reftype: ReferenceType,
pub other: String,
}
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Clone)]
pub struct Entity {
pub name: String,
pub attributes: Attributes,
pub references: References,
}
impl Default for Events {
fn default() -> Self {
Events {
change: Vec::<DocumentReference>::new(),
update: Vec::<DocumentReference>::new(),
read: Vec::<DocumentReference>::new(),
delete: Vec::<DocumentReference>::new(),
all: Vec::<DocumentReference>::new(),
}
}
}
impl Attribute {
pub fn new(name: &str, attr_type: &str) -> Self {
Attribute {
name: name.to_string().clone(),
vtype: attr_type.to_string().clone(),
default: "".to_string(),
validations: Validations::new(),
}
}
}
impl Domain {
pub fn has_entity(&mut self, name: &str) -> bool {
match self.get_entity(name) {
Ok(_) => true,
Err(_) => false,
}
}
pub fn get_entity(&mut self, name: &str) -> Result<&Entity, String> {
let mut res: Vec<&Entity> = self.entities
.iter()
.filter({
|e| e.name.eq(name)
})
.collect();
if res.len() == 1 {
Ok(&mut res[0])
} else {
Err(format!("Entity {} does not exist", name))
}
}
pub fn add_entity(&mut self, entity: Entity) -> Result<(), String> {
if self.has_entity(&entity.name) {
Err(format!("Entity {} already exists", entity.name))
} else {
self.entities.push(entity);
Ok(())
}
}
pub fn remove_entity(&mut self, entity: &str) -> Result<(), String> {
let entities = self.entities.clone();
self.entities = entities
.into_iter()
.filter({
|e| e.name.ne(entity)
})
.collect();
Ok(())
}
}
impl Default for Entity {
fn default() -> Self {
Entity {
name: "".to_owned(),
attributes: Attributes::new(),
references: References::new(),
}
}
}
impl Entity {
pub fn new(name: &str) -> Self {
Entity {
name: name.to_string().to_owned(),
attributes: Attributes::new(),
references: References::new(),
}
}
pub fn get_attribute(self, name: &str) -> Result<Attribute, String> {
let res: Vec<&Attribute> = self.attributes
.iter()
.filter({
|e| e.name.eq(name)
})
.collect();
if res.len() == 1 {
Ok(res[0].clone())
} else {
Err(format!("Attribute {} does not exist", name))
}
}
pub fn add_attribute(&mut self, attr: Attribute) -> Result<(), String> {
self.attributes.push(attr);
Ok(())
}
}
impl Default for Domain {
fn default() -> Self {
Domain {
events: Events::default(),
entities: Entities::new(),
}
}
}
impl Translatable for DomainDocument {
fn translate_in_place(&mut self, t: &TranslationDocument) -> () {
for entity in &mut self.body.entities {
for attribute in &mut entity.attributes {
for validation in &mut attribute.validations {
validation.message.translate_self(&t);
}
}
}
}
fn translate(&self, t: &TranslationDocument) -> DomainDocument {
let mut doc = self.clone();
doc.translate_in_place(&t);
doc
}
fn all_i18n_strings(&self) -> Vec<&I18NString> {
let mut ts = Vec::<&I18NString>::new();
for entity in &self.body.entities {
for attribute in &entity.attributes {
for validation in &attribute.validations {
ts.push(&validation.message);
}
}
}
ts
}
}