use crate::common::event::{Event, EventPayload};
use crate::common::related_party::RelatedParty;
use crate::common::tmf_error::TMFError;
use crate::tmf620::category::CategoryRef;
use crate::{
DateTime, HasDescription, HasId, HasLastUpdate, HasName, HasReference, HasRelatedParty,
HasValidity, TMFEvent, TimePeriod, Uri,
};
use tmflib_derive::{HasDescription, HasId, HasLastUpdate, HasName, HasRelatedParty, HasValidity};
use chrono::Utc;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use super::MOD_PATH;
const CLASS_PATH: &str = "catalog";
const CAT_VERS: &str = "1.0";
#[derive(
Clone,
Default,
Debug,
Deserialize,
HasLastUpdate,
HasId,
HasName,
HasDescription,
HasValidity,
HasRelatedParty,
Serialize,
)]
#[serde(rename_all = "camelCase")]
pub struct Catalog {
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub href: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
catalog_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
last_update: Option<DateTime>,
#[serde(skip_serializing_if = "Option::is_none")]
lifecycle_status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
valid_for: Option<TimePeriod>,
#[serde(skip_serializing_if = "Option::is_none")]
category: Option<Vec<CategoryRef>>,
#[serde(skip_serializing_if = "Option::is_none")]
related_party: Option<Vec<RelatedParty>>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@baseType")]
base_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@schemaLocation")]
schema_location: Option<Uri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@type")]
r#type: Option<String>,
}
impl Catalog {
pub fn new(name: impl Into<String>) -> Catalog {
let mut cat = Catalog::create_with_time();
cat.name = Some(name.into());
cat.version = Some(CAT_VERS.to_string());
cat.category = Some(vec![]);
cat.related_party = Some(vec![]);
cat.valid_for = Some(TimePeriod::default());
cat
}
pub fn name(mut self, name: String) -> Catalog {
self.name = Some(name.clone());
self
}
pub fn add_category(&mut self, category: CategoryRef) {
match self.category.as_mut() {
Some(v) => v.push(category),
None => self.category = Some(vec![category]),
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct CatalogEvent {
pub catalog: Catalog,
}
impl HasReference for Catalog {
type RefType = Catalog;
}
impl TMFEvent<CatalogEvent> for Catalog {
fn event(&self) -> CatalogEvent {
CatalogEvent {
catalog: self.clone(),
}
}
}
impl EventPayload<CatalogEvent> for Catalog {
type Subject = Catalog;
type EventType = CatalogEventType;
fn to_event(&self, event_type: CatalogEventType) -> Event<CatalogEvent, CatalogEventType> {
let now = Utc::now();
let event_time = chrono::DateTime::from_timestamp(now.timestamp(), 0).unwrap();
let desc = format!("{:?} for {}", event_type, self.get_name());
Event {
correlation_id: None,
description: Some(desc),
domain: Some(Catalog::get_class()),
event_id: Uuid::new_v4().to_string(),
field_path: None,
href: self.href.clone(),
id: self.id.clone(),
title: self.name.clone(),
event_time: event_time.to_string(),
priority: None,
time_occurred: None,
event_type,
event: self.event(),
}
}
}
#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub enum CatalogEventType {
CatalogCreateEvent,
CatalogDeleteEvent,
CatalogBatchEvent,
}
#[cfg(test)]
mod tests {
const CAT_NAME: &str = "A Catalog";
const CAT_DESC: &str = "A Description";
use crate::common::event::EventPayload;
use crate::common::related_party::RelatedParty;
use crate::tmf620::catalog::{CAT_VERS, CLASS_PATH};
#[cfg(all(feature = "tmf632", feature = "build-V4"))]
use crate::tmf632::organization_v4::Organization;
#[cfg(all(feature = "tmf632", feature = "build-V5"))]
use crate::tmf632::organization_v5::Organization;
use super::{Catalog, CatalogEvent, CatalogEventType};
use crate::tmf620::category::{Category, CategoryRef};
use crate::{HasDescription, HasId, HasName, HasRelatedParty, HasValidity, TimePeriod};
const CAT_JSON: &str = "{
\"name\" : \"CatalogueName\",
\"@baseType\" : \"catalog\"
}";
const CAT_EVENT_TYPE_JSON: &str = "\"CatalogCreateEvent\"";
const CATALOGEVENT_JSON: &str = "{
\"catalog\" : {}
}";
#[test]
fn test_cat_name() {
let cat = Catalog::new(CAT_NAME);
assert_eq!(cat.name, Some(String::from(CAT_NAME)));
}
#[test]
fn test_cat_vers() {
let cat = Catalog::new(CAT_NAME);
assert_eq!(cat.version, Some(CAT_VERS.to_string()));
}
#[test]
fn test_cat_class() {
assert_eq!(Catalog::get_class(), CLASS_PATH.to_owned());
}
#[test]
fn test_cat_rename() {
let cat = Catalog::new(CAT_NAME).name("NewName".to_string());
assert_eq!(cat.get_name(), "NewName".to_string());
}
#[test]
fn test_cat_add_cat() {
let mut cat = Catalog::new(CAT_NAME);
let category = Category::new("A Category");
cat.add_category(CategoryRef::from(&category));
assert_eq!(cat.category.is_some(), true);
}
#[test]
fn test_cat_add_party() {
let mut cat = Catalog::new(CAT_NAME);
let org = Organization::new("An Organisation");
cat.add_party(RelatedParty::from(&org));
assert_eq!(cat.related_party.is_some(), true);
}
#[test]
fn test_catalog_event() {
let cat = Catalog::new(CAT_NAME);
let event = cat.to_event(CatalogEventType::CatalogCreateEvent);
assert_eq!(event.domain.unwrap(), Catalog::get_class());
assert_eq!(event.href, cat.href);
assert_eq!(event.id, cat.id);
assert_eq!(event.title, cat.name);
}
#[test]
fn test_catalog_deserialize() {
let cat: Catalog = serde_json::from_str(CAT_JSON).unwrap();
assert_eq!(cat.name.is_some(), true);
assert_eq!(cat.get_name().as_str(), "CatalogueName");
}
#[test]
fn test_catalog_hasvalidity() {
let mut cat = Catalog::new(CAT_NAME);
cat.set_validity(TimePeriod::period_30days());
assert_eq!(cat.valid_for.is_some(), true);
assert_eq!(cat.valid_for.unwrap().started(), true);
}
#[test]
fn test_catalogeventtype_deserialize() {
let eventtype: CatalogEventType =
serde_json::from_str(CAT_EVENT_TYPE_JSON).expect("Could not parse CAT_EVENT_TYPE_JSON");
assert_eq!(eventtype, CatalogEventType::CatalogCreateEvent);
}
#[test]
fn test_catalogevent_deserialize() {
let _catalogevent: CatalogEvent =
serde_json::from_str(CATALOGEVENT_JSON).expect("Could not parse CATALOGEVENT_JSON");
}
#[test]
fn test_catalogeventtype_display() {
let catalogeventtype = CatalogEventType::CatalogCreateEvent;
println!("{:?}", catalogeventtype);
let catalogeventtype = CatalogEventType::CatalogBatchEvent;
println!("{:?}", catalogeventtype);
let catalogeventtype = CatalogEventType::CatalogDeleteEvent;
println!("{:?}", catalogeventtype);
}
#[test]
fn test_catalog_getpartybyrole() {
let mut cat = Catalog::new(CAT_NAME);
let org = Organization::new("An Organisation");
cat.add_party(RelatedParty::from(&org));
let party = cat.get_by_role(Organization::get_class());
assert_eq!(party.is_some(), true);
let party_vec = party.unwrap();
assert_eq!(party_vec.len(), 1);
let party_vec_first = party_vec.first();
assert_eq!(party_vec_first.is_some(), true);
let related_party = party_vec_first.unwrap();
assert_eq!(related_party.name, Some("An Organisation".to_string()));
}
#[test]
fn test_catalog_description() {
let cat = Catalog::new(CAT_NAME).description(CAT_DESC);
assert_eq!(cat.description.is_some(), true);
assert_eq!(cat.get_description(), CAT_DESC.to_string());
}
}