You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
220 lines
5.8 KiB
220 lines
5.8 KiB
//! Data model structs and enums
|
|
|
|
use std::fmt;
|
|
use std::fmt::{Display, Formatter};
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use super::data::TypedValue;
|
|
use super::ID;
|
|
use crate::id::HaveId;
|
|
use std::cmp::Ordering;
|
|
|
|
/// Get a description of a struct
|
|
pub trait Describe {
|
|
/// Short but informative description for error messages
|
|
fn describe(&self) -> String;
|
|
}
|
|
|
|
/// Object template
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ObjectModel {
|
|
/// PK
|
|
#[serde(default)]
|
|
pub id: ID,
|
|
/// Template name, unique within the database
|
|
pub name: String,
|
|
/// Property to use as the name in relation selectors
|
|
#[serde(default)]
|
|
pub name_property: Option<ID>,
|
|
/// Sort key, smaller go first
|
|
pub sort_key : i64,
|
|
}
|
|
|
|
/// Relation between templates
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct RelationModel {
|
|
/// PK
|
|
#[serde(default)]
|
|
pub id: ID,
|
|
/// Object template ID
|
|
pub object: ID,
|
|
/// Relation name, unique within the parent object
|
|
pub name: String,
|
|
/// Relation name when viewed from the other side, unique within the related object's relations
|
|
pub reciprocal_name: String,
|
|
/// Relation is optional
|
|
pub optional: bool,
|
|
/// Relation can be multiple
|
|
pub multiple: bool,
|
|
/// Related object template ID
|
|
pub related: ID,
|
|
/// Sort key, smaller go first
|
|
pub sort_key : i64,
|
|
}
|
|
|
|
/// Property definition
|
|
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
|
pub struct PropertyModel {
|
|
/// PK
|
|
#[serde(default)]
|
|
pub id: ID,
|
|
/// Object or Reference template ID
|
|
pub object: ID,
|
|
/// Property name, unique within the parent object or reference
|
|
pub name: String,
|
|
/// Property is optional
|
|
pub optional: bool,
|
|
/// Property can be multiple
|
|
pub multiple: bool,
|
|
/// Value must be unique among instances of the parent model
|
|
pub unique: bool,
|
|
/// Property data type
|
|
pub data_type: DataType,
|
|
/// Default value, used for newly created objects
|
|
pub default: TypedValue,
|
|
/// Sort key, smaller go first
|
|
pub sort_key : i64,
|
|
|
|
/// Additional presentational and data type specific config
|
|
pub options : PropertyOptions,
|
|
}
|
|
|
|
/// Additional presentational and data type specific config that shouldn't affect queries and such
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)]
|
|
pub struct PropertyOptions {
|
|
/// String should be shown as multi-line
|
|
pub multiline : bool,
|
|
}
|
|
|
|
/// Value data type
|
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Eq, PartialEq)]
|
|
pub enum DataType {
|
|
/// Text
|
|
String,
|
|
/// Integer
|
|
Integer,
|
|
/// Floating point number
|
|
Decimal,
|
|
/// Boolean yes/no
|
|
Boolean,
|
|
}
|
|
|
|
impl Display for ObjectModel {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
write!(f, "object \"{}\" ({})", self.name, self.id)
|
|
}
|
|
}
|
|
|
|
impl Display for RelationModel {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
write!(f, "relation \"{}\" ({})", self.name, self.id)
|
|
}
|
|
}
|
|
|
|
impl Display for PropertyModel {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
|
write!(f, "property \"{}\" ({})", self.name, self.id)
|
|
}
|
|
}
|
|
|
|
impl HaveId for ObjectModel {
|
|
fn get_id(&self) -> ID {
|
|
self.id
|
|
}
|
|
}
|
|
|
|
impl HaveId for RelationModel {
|
|
fn get_id(&self) -> ID {
|
|
self.id
|
|
}
|
|
}
|
|
|
|
impl HaveId for PropertyModel {
|
|
fn get_id(&self) -> ID {
|
|
self.id
|
|
}
|
|
}
|
|
|
|
// TODO find some less shitty way to do sorting
|
|
|
|
|
|
impl PropertyModel {
|
|
/// Get sort
|
|
pub fn order(one : &Self, another: &Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.name.cmp(&another.name))
|
|
}
|
|
|
|
// stupid intensifies
|
|
pub fn order_refs(one : &&Self, another: &&Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.name.cmp(&another.name))
|
|
}
|
|
|
|
// hello
|
|
pub fn order_refs2(one : &&&Self, another: &&&Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.name.cmp(&another.name))
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl ObjectModel {
|
|
/// Get sort
|
|
pub fn order(one : &Self, another: &Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.name.cmp(&another.name))
|
|
}
|
|
|
|
// stupid intensifies
|
|
pub fn order_refs(one : &&Self, another: &&Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.name.cmp(&another.name))
|
|
}
|
|
|
|
// hello
|
|
pub fn order_refs2(one : &&&Self, another: &&&Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.name.cmp(&another.name))
|
|
}
|
|
}
|
|
|
|
impl RelationModel {
|
|
/// Get sort
|
|
pub fn order(one : &Self, another: &Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.name.cmp(&another.name))
|
|
}
|
|
|
|
// stupid intensifies
|
|
pub fn order_refs(one : &&Self, another: &&Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.name.cmp(&another.name))
|
|
}
|
|
|
|
// hello
|
|
pub fn order_refs2(one : &&&Self, another: &&&Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.name.cmp(&another.name))
|
|
}
|
|
|
|
|
|
// more stupid
|
|
|
|
pub fn reciprocal_order(one : &Self, another: &Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.reciprocal_name.cmp(&another.reciprocal_name))
|
|
}
|
|
|
|
pub fn reciprocal_order_refs(one : &&Self, another: &&Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.reciprocal_name.cmp(&another.reciprocal_name))
|
|
}
|
|
|
|
pub fn reciprocal_order_refs2(one : &&&Self, another: &&&Self) -> Ordering {
|
|
one.sort_key.cmp(&another.sort_key)
|
|
.then_with(|| one.reciprocal_name.cmp(&another.reciprocal_name))
|
|
}
|
|
}
|
|
|