use super::{HostRef, ServiceCheckRef, TimeZone};
use crate::{prelude::*, util::*};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
pub struct TimePeriod {
pub name: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub alias: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub friday: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub monday: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub saturday: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sunday: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub thursday: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tuesday: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub wednesday: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub zone: Option<TimeZone>,
#[serde(skip_serializing_if = "Option::is_none")]
pub host_check_periods: Option<ConfigRefMap<HostRef>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub host_notification_periods: Option<ConfigRefMap<HostRef>>,
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_string_or_number_to_u64",
default
)]
pub id: Option<u64>,
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_string_or_number_to_option_bool",
serialize_with = "serialize_option_bool_as_string",
default
)]
pub object_locked: Option<bool>,
#[serde(
rename = "ref",
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_readonly",
default
)]
pub ref_: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub servicecheck_check_periods: Option<ConfigRefMap<ServiceCheckRef>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub servicecheck_notification_periods: Option<ConfigRefMap<ServiceCheckRef>>,
#[serde(
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_string_or_number_to_option_bool",
serialize_with = "serialize_option_bool_as_string",
default
)]
pub uncommitted: Option<bool>,
}
impl Default for TimePeriod {
fn default() -> Self {
let tz = TimeZone::builder()
.name("SYSTEM")
.ref_("/rest/config/timezone/1")
.build()
.unwrap();
TimePeriod {
name: String::new(),
alias: None,
friday: None,
host_check_periods: None,
host_notification_periods: None,
id: None,
monday: None,
object_locked: None,
ref_: None,
saturday: None,
servicecheck_check_periods: None,
servicecheck_notification_periods: None,
sunday: None,
thursday: None,
tuesday: None,
uncommitted: None,
wednesday: None,
zone: Some(tz),
}
}
}
impl CreateFromJson for TimePeriod {}
impl ConfigObject for TimePeriod {
type Builder = TimePeriodBuilder;
fn builder() -> Self::Builder {
TimePeriodBuilder::new()
}
fn config_path() -> Option<String> {
Some("/config/timeperiod".to_string())
}
fn unique_name(&self) -> String {
self.name.clone()
}
fn minimal(name: &str) -> Result<Self, OpsviewConfigError> {
Ok(Self {
name: validate_and_trim_timeperiod_name(name)?,
..Default::default()
})
}
}
impl Persistent for TimePeriod {
fn id(&self) -> Option<u64> {
self.id
}
fn ref_(&self) -> Option<String> {
if self.ref_.as_ref().is_some_and(|x| !x.is_empty()) {
self.ref_.clone()
} else {
None
}
}
fn name(&self) -> Option<String> {
if self.name.is_empty() {
None
} else {
Some(self.name.clone())
}
}
fn name_regex(&self) -> Option<String> {
Some(TIMEPERIOD_NAME_REGEX_STR.to_string())
}
fn validated_name(&self, name: &str) -> Result<String, OpsviewConfigError> {
validate_and_trim_timeperiod_name(name)
}
fn set_name(&mut self, new_name: &str) -> Result<String, OpsviewConfigError> {
self.name = self.validated_name(new_name)?;
Ok(self.name.clone())
}
fn clear_readonly(&mut self) {
self.host_check_periods = None;
self.host_notification_periods = None;
self.id = None;
self.object_locked = None;
self.ref_ = None;
self.servicecheck_check_periods = None;
self.servicecheck_notification_periods = None;
self.uncommitted = None;
}
}
impl PersistentMap for ConfigObjectMap<TimePeriod> {
fn config_path() -> Option<String> {
Some("/config/timeperiod".to_string())
}
}
#[derive(Clone, Debug, Default)]
pub struct TimePeriodBuilder {
alias: Option<String>,
friday: Option<String>,
monday: Option<String>,
name: Option<String>,
saturday: Option<String>,
sunday: Option<String>,
thursday: Option<String>,
tuesday: Option<String>,
wednesday: Option<String>,
zone: Option<TimeZone>,
}
impl Builder for TimePeriodBuilder {
type ConfigObject = TimePeriod;
fn new() -> Self {
Self::default()
}
fn name(mut self, name: &str) -> Self {
self.name = Some(name.to_string());
self
}
fn build(self) -> Result<Self::ConfigObject, OpsviewConfigError> {
let name = require_field(&self.name, "name")?;
let validated_alias = validate_opt_string(self.alias, validate_and_trim_timeperiod_alias)?;
let validated_monday =
validate_opt_string(self.monday, validate_and_trim_timeperiod_weekday)?;
let validated_tuesday =
validate_opt_string(self.tuesday, validate_and_trim_timeperiod_weekday)?;
let validated_wednesday =
validate_opt_string(self.wednesday, validate_and_trim_timeperiod_weekday)?;
let validated_thursday =
validate_opt_string(self.thursday, validate_and_trim_timeperiod_weekday)?;
let validated_friday =
validate_opt_string(self.friday, validate_and_trim_timeperiod_weekday)?;
let validated_saturday =
validate_opt_string(self.saturday, validate_and_trim_timeperiod_weekday)?;
let validated_sunday =
validate_opt_string(self.sunday, validate_and_trim_timeperiod_weekday)?;
Ok(TimePeriod {
name: validate_and_trim_timeperiod_name(&name)?,
alias: validated_alias,
friday: validated_friday,
monday: validated_monday,
saturday: validated_saturday,
sunday: validated_sunday,
thursday: validated_thursday,
tuesday: validated_tuesday,
wednesday: validated_wednesday,
zone: self.zone,
host_check_periods: None,
host_notification_periods: None,
id: None,
object_locked: None,
ref_: None,
servicecheck_check_periods: None,
servicecheck_notification_periods: None,
uncommitted: None,
})
}
}
impl TimePeriodBuilder {
pub fn alias(mut self, alias: &str) -> Self {
self.alias = Some(alias.to_string());
self
}
pub fn clear_alias(mut self) -> Self {
self.alias = None;
self
}
pub fn clear_friday(mut self) -> Self {
self.friday = None;
self
}
pub fn clear_monday(mut self) -> Self {
self.monday = None;
self
}
pub fn clear_name(mut self) -> Self {
self.name = None;
self
}
pub fn clear_saturday(mut self) -> Self {
self.saturday = None;
self
}
pub fn clear_sunday(mut self) -> Self {
self.sunday = None;
self
}
pub fn clear_thursday(mut self) -> Self {
self.thursday = None;
self
}
pub fn clear_tuesday(mut self) -> Self {
self.tuesday = None;
self
}
pub fn clear_wednesday(mut self) -> Self {
self.wednesday = None;
self
}
pub fn clear_zone(mut self) -> Self {
self.zone = None;
self
}
pub fn friday(mut self, friday: &str) -> Self {
self.friday = Some(friday.to_string());
self
}
pub fn monday(mut self, monday: &str) -> Self {
self.monday = Some(monday.to_string());
self
}
pub fn saturday(mut self, saturday: &str) -> Self {
self.saturday = Some(saturday.to_string());
self
}
pub fn sunday(mut self, sunday: &str) -> Self {
self.sunday = Some(sunday.to_string());
self
}
pub fn thursday(mut self, thursday: &str) -> Self {
self.thursday = Some(thursday.to_string());
self
}
pub fn tuesday(mut self, tuesday: &str) -> Self {
self.tuesday = Some(tuesday.to_string());
self
}
pub fn wednesday(mut self, wednesday: &str) -> Self {
self.wednesday = Some(wednesday.to_string());
self
}
pub fn zone(mut self, zone: TimeZone) -> Self {
self.zone = Some(zone);
self
}
}
#[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)]
pub struct TimePeriodRef {
name: String,
#[serde(
rename = "ref",
skip_serializing_if = "Option::is_none",
deserialize_with = "deserialize_readonly",
default
)]
ref_: Option<String>,
}
impl CreateFromJson for TimePeriodRef {}
impl ConfigRef for TimePeriodRef {
type FullObject = TimePeriod;
fn ref_(&self) -> Option<String> {
self.ref_.clone()
}
fn name(&self) -> String {
self.name.clone()
}
fn unique_name(&self) -> String {
self.name.clone()
}
}
impl From<TimePeriod> for TimePeriodRef {
fn from(timeperiod: TimePeriod) -> Self {
TimePeriodRef {
name: timeperiod.name.clone(),
ref_: timeperiod.ref_.clone(),
}
}
}
impl From<Arc<TimePeriod>> for TimePeriodRef {
fn from(timeperiod: Arc<TimePeriod>) -> Self {
TimePeriodRef {
name: timeperiod.name.clone(),
ref_: timeperiod.ref_.clone(),
}
}
}
impl From<&ConfigObjectMap<TimePeriod>> for ConfigRefMap<TimePeriodRef> {
fn from(timeperiods: &ConfigObjectMap<TimePeriod>) -> Self {
ref_map_from(timeperiods)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_timeperiod_default() {
let tz = TimeZone::builder()
.name("SYSTEM")
.ref_("/rest/config/timezone/1")
.build()
.unwrap();
let timeperiod = TimePeriod::default();
assert_eq!(timeperiod.name, String::new());
assert_eq!(timeperiod.alias, None);
assert_eq!(timeperiod.friday, None);
assert_eq!(timeperiod.host_check_periods, None);
assert_eq!(timeperiod.host_notification_periods, None);
assert_eq!(timeperiod.id, None);
assert_eq!(timeperiod.monday, None);
assert_eq!(timeperiod.object_locked, None);
assert_eq!(timeperiod.ref_, None);
assert_eq!(timeperiod.saturday, None);
assert_eq!(timeperiod.servicecheck_check_periods, None);
assert_eq!(timeperiod.servicecheck_notification_periods, None);
assert_eq!(timeperiod.sunday, None);
assert_eq!(timeperiod.thursday, None);
assert_eq!(timeperiod.tuesday, None);
assert_eq!(timeperiod.uncommitted, None);
assert_eq!(timeperiod.wednesday, None);
assert_eq!(timeperiod.zone, Some(tz));
}
#[test]
fn test_timeperiod_minimal() {
let timeperiod = TimePeriod::minimal("MyTimePeriod");
assert_eq!(timeperiod.unwrap().name, "MyTimePeriod".to_string());
}
#[test]
fn test_is_valid_timeperiod_name() {
assert!(validate_and_trim_timeperiod_name("24x7").is_ok());
assert!(validate_and_trim_timeperiod_name("My Time Period").is_err());
}
#[test]
fn test_valid_timeperiods() {
let valid_strings = [
"00:00-09:00,17:00-24:00",
"00:00-24:00",
"00:00-09:00,10:00-11:00,12:00-24:00",
];
for s in valid_strings {
println!("Testing timeperiod string '{}'", s);
let tp = TimePeriod::builder()
.name("foo")
.monday(s)
.tuesday(s)
.wednesday(s)
.thursday(s)
.friday(s)
.saturday(s)
.sunday(s)
.build();
assert!(tp.is_ok());
}
}
#[test]
fn test_invalid_timeperiods() {
let invalid_strings = ["foo", "00:00-22:00 23:00-24:00", "10:00-11:00Z", ""];
for s in invalid_strings {
println!("Testing timeperiod string '{}'", s);
let tp = TimePeriod::builder()
.name("foo")
.monday(s)
.tuesday(s)
.wednesday(s)
.thursday(s)
.friday(s)
.saturday(s)
.sunday(s)
.build();
assert!(tp.is_err());
}
}
}