use url::Url;
use crate::{
namespace::SystemNamespaceUrl, BodyListId, DateTime, EmailAddress, Name, OParlVersion, SystemId,
};
#[derive(
Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
)]
#[serde(rename_all = "camelCase")]
pub struct System {
pub id: SystemId,
#[serde(rename = "type")]
pub namespace: SystemNamespaceUrl,
pub oparl_version: OParlVersion,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub other_oparl_versions: Vec<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub license: Option<Url>,
pub body: BodyListId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub contact_email: Option<EmailAddress>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub contact_name: Option<Name>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub website: Option<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub vendor: Option<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub product: Option<Url>,
pub created: DateTime,
pub modified: DateTime,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub web: Option<Url>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub deleted: Option<bool>,
}
#[cfg(test)]
mod serde_tests {
use super::System;
use crate::{namespace::SystemNamespaceUrl, OParlVersion};
use pretty_assertions::assert_eq;
use serde_json::json;
use time::macros::datetime;
fn example_system() -> System {
System {
id: "https://oparl.example.org/"
.parse()
.expect("value must be parseable as id"),
namespace: SystemNamespaceUrl::Identifier,
oparl_version: OParlVersion::Version1_1,
other_oparl_versions: vec!["https://oparl2.example.org/"
.parse()
.expect("value must be parseable as url")],
license: None,
body: "https://oparl.example.org/bodies"
.parse()
.expect("value must be parseable as url"),
name: Some(
"Beispiel-System"
.parse()
.expect("value must be parseable as name"),
),
contact_email: Some(
"info@example.org"
.parse()
.expect("value must be parseable as email"),
),
contact_name: Some(
"Allgemeiner OParl Kontakt"
.parse()
.expect("value must be parseable as name"),
),
website: Some(
"http://www.example.org/"
.parse()
.expect("value must be parseable as url"),
),
vendor: Some(
"http://example-software.com/"
.parse()
.expect("value must be parseable as url"),
),
product: Some(
"http://example-software.com/oparl-server/"
.parse()
.expect("value must be parseable as url"),
),
created: datetime!(2011-11-11 11:11:00 +01:00).into(),
modified: datetime!(2012-11-11 11:11:00 +01:00).into(),
web: None,
deleted: None,
}
}
fn example_system_json() -> serde_json::Value {
json!({
"id": "https://oparl.example.org/",
"type": "https://schema.oparl.org/1.1/System",
"oparlVersion": "https://schema.oparl.org/1.1/",
"body": "https://oparl.example.org/bodies",
"name": "Beispiel-System",
"contactEmail": "info@example.org",
"contactName": "Allgemeiner OParl Kontakt",
"website": "http://www.example.org/",
"vendor": "http://example-software.com/",
"product": "http://example-software.com/oparl-server/",
"otherOparlVersions": [
"https://oparl2.example.org/"
],
"created": "2011-11-11T11:11:00+01:00",
"modified": "2012-11-11T11:11:00+01:00"
})
}
#[test]
fn serialize() {
assert_eq!(json!(example_system()), example_system_json());
}
#[test]
fn deserialize_good() {
let deserialized: System = serde_json::from_value(example_system_json())
.expect("value must be deserializable as System");
assert_eq!(deserialized, example_system());
}
#[test]
fn deserialize_bad() {
assert!(serde_json::from_value::<System>(json!("xyzabcd")).is_err());
assert!(serde_json::from_value::<System>(json!(true)).is_err());
assert!(serde_json::from_value::<System>(json!(123)).is_err());
}
}