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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
use yaserde_derive::{YaDeserialize, YaSerialize};

use crate::Lang;

/// A container for the metadata necessary for an agent to identify a source(s).
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, YaSerialize, YaDeserialize, PartialEq, Clone, Default)]
#[yaserde(
    prefix = "gx",
    default_namespace = "gx",
    namespace = "gx: http://gedcomx.org/v1/"
)]
#[non_exhaustive]
pub struct SourceCitation {
    /// The locale identifier for the bibliographic metadata.
    #[yaserde(attribute, prefix = "xml")]
    pub lang: Option<Lang>,

    /// The bibliographic metadata rendered as a full citation.
    ///
    ///  This string is plain text, but MAY include an xhtml cite element. If
    /// the value includes a cite element, the text-level semantics defined for
    /// cite MUST apply—i.e., the element MUST represent the title of a work.
    #[yaserde(prefix = "gx")]
    pub value: String,
}

impl SourceCitation {
    pub fn new<I: Into<String>>(value: I, lang: Option<Lang>) -> Self {
        Self {
            lang,
            value: value.into(),
        }
    }
}

#[cfg(test)]
mod test {
    use pretty_assertions::assert_eq;

    use super::super::*;

    #[test]
    fn json_deserialize() {
        let json = r#"{
            "lang" : "en",
            "value" : "a rendering of the full citation as a string"
        }"#;

        let source_citation: SourceCitation = serde_json::from_str(json).unwrap();
        assert_eq!(
            source_citation,
            SourceCitation {
                lang: Some("en".into()),
                value: "a rendering of the full citation as a string".to_string(),
            }
        )
    }

    #[test]
    fn xml_deserialize() {
        let xml = r#"  <SourceCitation xml:lang="en">
        <value>a rendering of the full citation as a string</value>    
      </SourceCitation>"#;

        let source_citation: SourceCitation = yaserde::de::from_str(xml).unwrap();
        assert_eq!(
            source_citation,
            SourceCitation {
                lang: Some("en".into()),
                value: "a rendering of the full citation as a string".to_string(),
            }
        )
    }

    #[test]
    fn json_deserialize_optional_fields() {
        let json = r#"{
            "value" : "a rendering of the full citation as a string"
        }"#;

        let source_citation: SourceCitation = serde_json::from_str(json).unwrap();
        assert_eq!(
            source_citation,
            SourceCitation::new(
                "a rendering of the full citation as a string".to_string(),
                None
            )
        )
    }

    #[test]
    fn json_serialize() {
        let source_citation = SourceCitation {
            lang: Some("en".into()),
            value: "a rendering of the full citation as a string".to_string(),
        };

        let json = serde_json::to_string(&source_citation).unwrap();

        assert_eq!(
            json,
            r#"{"lang":"en","value":"a rendering of the full citation as a string"}"#
        )
    }

    #[test]
    fn xml_serialize() {
        let source_citation = SourceCitation {
            lang: Some("en".into()),
            value: "a rendering of the full citation as a string".to_string(),
        };

        let config = yaserde::ser::Config {
            write_document_declaration: false,
            ..yaserde::ser::Config::default()
        };

        let xml = yaserde::ser::to_string_with_config(&source_citation, &config).unwrap();

        assert_eq!(
            xml,
            r#"<SourceCitation xmlns="http://gedcomx.org/v1/" xml:lang="en"><value>a rendering of the full citation as a string</value></SourceCitation>"#
        )
    }

    #[test]
    fn json_serialize_optional_fields() {
        let source_citation = SourceCitation::new(
            "a rendering of the full citation as a string".to_string(),
            None,
        );

        let json = serde_json::to_string(&source_citation).unwrap();

        assert_eq!(
            json,
            r#"{"value":"a rendering of the full citation as a string"}"#
        )
    }
}