use serde;
use serde_json;
use serde_yaml;
use uuid::Uuid;
use crate::structure::translation::TranslationDocument;
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct Document<T> {
pub id: Uuid,
pub name: String,
pub doctype: String,
pub doctype_version: i64,
pub version: i64,
pub body: T,
}
pub type DocumentList<T> = Vec<Document<T>>;
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct DocumentReference {
pub id: Uuid,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum ModelLoadError {
UnParseable(String),
BadStructure(String),
InputError(String),
}
pub trait DocumentNature {
type Doc;
fn new_from_header(header: &DocumentHeader) -> Self::Doc;
fn get_header(&self) -> DocumentHeader;
fn set_header(&mut self, header: &DocumentHeader) -> ();
fn to_string(&self) -> String;
fn summary(&self) -> String;
fn to_json(&self) -> String;
fn to_json_compact(&self) -> String;
fn from_json(s: &str) -> Result<Self::Doc, ModelLoadError>;
fn update_from_json(&mut self, s: &str) -> Result<&Self::Doc, String>;
fn to_yaml(&self) -> String;
fn from_yaml(s: &str) -> Result<Self::Doc, ModelLoadError>;
fn update_from_yaml(&mut self, s: &str) -> Result<&Self::Doc, String>;
}
pub trait DocumentFileSystemLoadable {
type Doc;
fn load_from_filesystem(path: &str) -> Result<Self::Doc, ModelLoadError>;
fn write_to_filesystem(&self, path: &str) -> Result<(), ModelLoadError>;
}
impl<T> DocumentNature for Document<T>
where
T: serde::Serialize + serde::de::DeserializeOwned + Eq + Default,
{
type Doc = Document<T>;
fn new_from_header(header: &DocumentHeader) -> Self {
Self {
id: header.id.clone(),
name: header.name.clone(),
doctype: header.doctype.clone(),
doctype_version: header.doctype_version.clone(),
version: header.version.clone(),
body: <T>::default(),
}
}
fn get_header(&self) -> DocumentHeader {
DocumentHeader {
id: self.id.clone(),
name: self.name.clone(),
doctype: self.doctype.clone(),
doctype_version: self.doctype_version.clone(),
version: self.version.clone(),
}
}
fn set_header(&mut self, header: &DocumentHeader) -> () {
self.id = header.id.clone();
self.name = header.name.clone();
self.doctype = header.doctype.clone();
self.doctype_version = header.doctype_version.clone();
self.version = header.version.clone();
}
fn to_string(&self) -> String {
self.summary()
}
fn summary(&self) -> String {
format!("Doc {:?} - {:?} - {:?}", self.doctype, self.id, self.name)
}
fn to_json(&self) -> String {
serde_json::to_string_pretty(&self).unwrap()
}
fn to_json_compact(&self) -> String {
serde_json::to_string(&self).unwrap()
}
fn from_json(s: &str) -> Result<Self::Doc, ModelLoadError> {
match serde_json::from_str(s) {
Ok(res) => Ok(res),
Err(err) => {
let msg = format!("{}", err);
Err(ModelLoadError::BadStructure(msg))
}
}
}
fn update_from_json(&mut self, s: &str) -> Result<&Self, String> {
let value = serde_json::from_str(s).unwrap();
*self = serde_json::from_value(value).unwrap();
Ok(self)
}
fn to_yaml(&self) -> String {
serde_yaml::to_string(&self).unwrap()
}
fn from_yaml(s: &str) -> Result<Self, ModelLoadError> {
match serde_yaml::from_str(s) {
Ok(res) => Ok(res),
Err(err) => {
let msg = format!("{}", err);
Err(ModelLoadError::BadStructure(msg))
}
}
}
fn update_from_yaml(&mut self, s: &str) -> Result<&Self, String> {
let value = serde_yaml::from_str(s).unwrap();
*self = serde_yaml::from_value(value).unwrap();
Ok(self)
}
}
impl<T> Default for Document<T>
where
T: Default,
{
fn default() -> Self {
Self {
id: Uuid::new_v4(),
name: "default".to_owned(),
doctype: "".to_owned(),
doctype_version: 1,
version: 1,
body: <T>::default(),
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
pub struct I18NString {
pub locale: String,
pub key: String,
pub value: String,
}
impl I18NString {
pub fn new(s: String) -> I18NString {
I18NString {
locale: "".to_owned(),
key: "".to_owned(),
value: s,
}
}
}
impl Default for I18NString {
fn default() -> I18NString {
I18NString {
locale: "".to_owned(),
key: "".to_owned(),
value: "".to_owned(),
}
}
}
impl I18NString {
pub fn translate(&self, t: &TranslationDocument) -> Self {
I18NString {
locale: t.body.locale.clone(),
key: self.key.clone(),
value: t.body
.items
.get(&self.key)
.unwrap_or(&I18NString::new("".to_owned()))
.value
.clone(),
}
}
pub fn translate_self(&mut self, t: &TranslationDocument) -> () {
match t.body.items.get(&self.key) {
Some(item) => {
self.locale = item.locale.clone();
self.value = item.value.clone();
}
None => {
warn!(
"No translation found for '{:?}' in locale '{:?}'",
self.key,
t.body.locale
);
self.locale = t.body.locale.clone();
self.value = "-no-value-".to_owned();
}
};
debug!("Translated value is '{:?}'", self.value);
}
}
pub trait Translatable {
fn translate_in_place(&mut self, t: &TranslationDocument) -> ();
fn translate(&self, t: &TranslationDocument) -> Self;
fn all_i18n_strings(&self) -> Vec<&I18NString>;
}
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct DocumentHeader {
pub id: Uuid,
pub name: String,
pub doctype: String,
pub doctype_version: i64,
pub version: i64,
}
impl DocumentHeader {
pub fn to_string(&self) -> String {
format!("document {}", self.id)
}
pub fn to_json(&self) -> String {
serde_json::to_string_pretty(&self).unwrap()
}
pub fn to_json_compact(&self) -> String {
serde_json::to_string(&self).unwrap()
}
pub fn from_json(s: &str) -> Result<Self, ModelLoadError> {
match serde_json::from_str(s) {
Ok(res) => Ok(res),
Err(err) => {
let msg = format!("{}", err);
Err(ModelLoadError::BadStructure(msg))
}
}
}
pub fn to_yaml(&self) -> String {
serde_yaml::to_string(&self).unwrap()
}
pub fn from_yaml(s: &str) -> Result<Self, ModelLoadError> {
match serde_yaml::from_str(s) {
Ok(res) => Ok(res),
Err(err) => {
let msg = format!("{}", err);
Err(ModelLoadError::BadStructure(msg))
}
}
}
}