use chrono::Utc;
use serde::{Deserialize, Serialize};
use crate::common::event::{Event, EventPayload};
use crate::{
vec_insert, HasDescription, HasId, HasLastUpdate, HasName, HasValidity, TMFEvent, TimePeriod,
TimeStamp, Uri,
};
use tmflib_derive::{HasDescription, HasId, HasLastUpdate, HasName, HasValidity};
use super::{service_candidate::ServiceCandidateRef, MOD_PATH};
const CLASS_PATH: &str = "serviceCategory";
const CAT_STATUS_NEW: &str = "new";
const CAT_VERS_NEW: &str = "1.0";
#[derive(Clone, Default, Debug, Deserialize, Serialize)]
pub struct ServiceCategoryRef {
href: Uri,
id: String,
name: String,
version: Option<String>,
}
impl From<ServiceCategory> for ServiceCategoryRef {
fn from(value: ServiceCategory) -> Self {
ServiceCategoryRef {
href: value.get_href(),
id: value.get_id(),
name: value.get_name(),
version: value.version.clone(),
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub enum ServiceCategoryEventType {
#[default]
ServiceCategoryCreateEvent,
ServiceCategoryChangeEvent,
ServiceCategoryDeleteEvent,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct ServiceCategoryEvent {
category: ServiceCategory,
}
impl TMFEvent<ServiceCategoryEvent> for ServiceCategory {
fn event(&self) -> ServiceCategoryEvent {
ServiceCategoryEvent {
category: self.clone(),
}
}
}
impl EventPayload<ServiceCategoryEvent> for ServiceCategory {
type Subject = ServiceCategory;
type EventType = ServiceCategoryEventType;
fn to_event(
&self,
event_type: Self::EventType,
) -> Event<ServiceCategoryEvent, Self::EventType> {
let now = Utc::now();
let desc = format!(
"{:?} for {} [{}]",
event_type,
self.get_name(),
self.get_id()
);
let event_time = chrono::DateTime::from_timestamp(now.timestamp(), 0).unwrap();
Event {
id: self.id.clone(),
href: self.href.clone(),
description: Some(desc),
title: self.name.clone(),
domain: Some(ServiceCategory::get_class()),
event_type,
event_time: event_time.to_string(),
event: self.event(),
time_occurred: Some(event_time.to_string()),
..Default::default()
}
}
}
#[derive(
Clone,
Debug,
Default,
Deserialize,
HasId,
HasName,
HasDescription,
HasLastUpdate,
HasValidity,
Serialize,
)]
pub struct ServiceCategory {
#[serde(skip_serializing_if = "Option::is_none")]
description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
href: Option<Uri>,
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
is_root: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
last_update: Option<TimeStamp>,
#[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")]
parent_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
valid_for: Option<TimePeriod>,
#[serde(skip_serializing_if = "Option::is_none")]
version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@baseType")]
pub base_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@schemaLocation")]
pub schema_location: Option<Uri>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "@type")]
pub r#type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
category: Option<Vec<ServiceCategoryRef>>,
#[serde(skip_serializing_if = "Option::is_none")]
service_candidate: Option<Vec<ServiceCandidateRef>>,
}
impl ServiceCategory {
pub fn new(name: impl Into<String>) -> ServiceCategory {
ServiceCategory {
name: Some(name.into()),
lifecycle_status: Some(CAT_STATUS_NEW.into()),
version: Some(CAT_VERS_NEW.into()),
..ServiceCategory::create_with_time()
}
}
pub fn child_category(mut self, category: ServiceCategoryRef) -> ServiceCategory {
vec_insert(&mut self.category, category);
self
}
pub fn candidate(mut self, candidate: ServiceCandidateRef) -> ServiceCategory {
vec_insert(&mut self.service_candidate, candidate);
self
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::tmf633::service_candidate::ServiceCandidate;
const CAT_NAME: &str = "CAT_NAME";
const CHILD_CAT: &str = "CHILD_CAT";
const CANDIDATE_NAME: &str = "CANDIDATE_NAME";
#[test]
fn test_servicecategory_create() {
let category = ServiceCategory::new(CAT_NAME);
assert_eq!(category.get_name(), CAT_NAME.to_string());
}
#[test]
fn test_category_into_ref() {
let category = ServiceCategory::new(CAT_NAME);
let cat_ref: ServiceCategoryRef = category.into();
assert_eq!(CAT_NAME.to_string(), cat_ref.name);
}
#[test]
fn test_category_addchild() {
let child_cat = ServiceCategory::new(CHILD_CAT);
let parent_cat =
ServiceCategory::new(CAT_NAME).child_category(ServiceCategoryRef::from(child_cat));
assert_eq!(parent_cat.category.is_some(), true);
assert_eq!(parent_cat.category.unwrap().len(), 1);
}
#[test]
fn test_category_addcandidate() {
let mut candidate = ServiceCandidate::default();
candidate.generate_id();
candidate.set_name(CANDIDATE_NAME);
let category =
ServiceCategory::new(CAT_NAME).candidate(ServiceCandidateRef::from(candidate));
assert_eq!(category.service_candidate.is_some(), true);
assert_eq!(category.service_candidate.unwrap().len(), 1);
}
}