1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Service Specification Module

use serde::{Deserialize,Serialize};

use crate::{HasId,HasName,HasLastUpdate, TimePeriod};
use crate::common::related_party::RelatedParty;
use tmflib_derive::{HasId,HasName,HasLastUpdate};

use super::MOD_PATH;
use crate::LIB_PATH;

const CLASS_PATH : &str = "service";

use super::characteristic_specification::CharacteristicSpecification;

/// Service Specification
#[derive(Clone,Default,Debug,Deserialize, HasId, HasName, HasLastUpdate, Serialize)]
pub struct ServiceSpecification {
    /// Unique Id
    #[serde(skip_serializing_if = "Option::is_none")]
    pub id : Option<String>,
    /// HREF 
    #[serde(skip_serializing_if = "Option::is_none")]
    pub href : Option<String>,
    /// Name
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name : Option<String>,
    /// Last Update
    #[serde(skip_serializing_if = "Option::is_none")]
    pub last_update : Option<String>,
    /// Description
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description : Option<String>,
    /// Is this specification part of a bundle?
    #[serde(skip_serializing_if = "Option::is_none")]
    pub is_bundle: Option<bool>,
    /// Status of this specification
    #[serde(skip_serializing_if = "Option::is_none")]
    pub lifecycle_status: Option<String>,
    /// Validity period
    #[serde(skip_serializing_if = "Option::is_none")]
    pub valid_for : Option<TimePeriod>,
    /// Versioning
    #[serde(skip_serializing_if = "Option::is_none")]
    pub version: Option<String>,
    /// Characteristics
    #[serde(skip_serializing_if = "Option::is_none")]
    pub spec_characteristics: Option<Vec<CharacteristicSpecification>>,
    /// Related Parties
    #[serde(skip_serializing_if = "Option::is_none")]
    pub related_party: Option<Vec<RelatedParty>>,
}

impl ServiceSpecification {
    /// Create a new specification
    pub fn new(name : impl Into<String>) -> ServiceSpecification {
        let mut ss = ServiceSpecification::create_with_time();
        ss.name = Some(name.into());
        ss.spec_characteristics = Some(vec![]);
        ss.is_bundle = Some(false);
        ss.lifecycle_status = Some("New".to_string());
        ss
    }

    /// Add a characteristic to this service specification
    pub fn add_char(&mut self, characteristic : CharacteristicSpecification) {
        self.spec_characteristics.as_mut().unwrap().push(characteristic);
    }
}

/// Reference to Service Specification
#[derive(Clone,Default,Debug,Deserialize,Serialize)]
pub struct ServiceSpecificationRef {
    /// Unique Id
    pub id : String,
    /// Uri 
    pub href : String,
    /// Name
    pub name: String,
    /// Version
    pub version: Option<String>,
}

impl From<ServiceSpecification> for ServiceSpecificationRef {
    fn from(value: ServiceSpecification) -> Self {
        ServiceSpecificationRef {
            id : value.get_id(),
            href: value.get_href(),
            name: value.get_name(),
            version: value.version.clone(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    const SPEC_NAME :&str = "ServiceSpecification";

    #[test]
    fn test_specification_new() {
        let spec = ServiceSpecification::new(SPEC_NAME);

        assert_eq!(spec.get_name().as_str(),SPEC_NAME);
        assert_eq!(spec.is_bundle.is_some(),true);
        assert_eq!(spec.is_bundle.unwrap(),false);
        assert_eq!(spec.lifecycle_status.is_some(),true);
        assert_eq!(spec.lifecycle_status.unwrap().as_str(),"New");
    }

    #[test]
    fn test_specref_from_specification() {
        let spec = ServiceSpecification::new(SPEC_NAME);

        let spec_ref = ServiceSpecificationRef::from(spec.clone());

        assert_eq!(spec.get_name(),spec_ref.name);
        assert_eq!(spec.get_id(),spec_ref.id);
        assert_eq!(spec.get_href(),spec_ref.href);
        assert_eq!(spec_ref.version.is_none(),true);
    }
}