use std::num::NonZeroU64;
use crate::{
EMLError, NS_EML,
io::{EMLElement, EMLElementReader, EMLElementWriter, QualifiedName, collect_struct},
utils::{CandidateId, NameShortCode, StringValue},
};
#[derive(Debug, Clone)]
pub struct CandidateIdentifier {
pub id: StringValue<CandidateId>,
pub display_order: Option<StringValue<NonZeroU64>>,
pub short_code: Option<StringValue<NameShortCode>>,
pub expected_confirmation_reference: Option<String>,
}
impl CandidateIdentifier {
pub fn new(id: CandidateId) -> Self {
CandidateIdentifier {
id: StringValue::Parsed(id),
display_order: None,
short_code: None,
expected_confirmation_reference: None,
}
}
pub fn with_display_order(mut self, display_order: NonZeroU64) -> Self {
self.display_order = Some(StringValue::Parsed(display_order));
self
}
pub fn with_short_code(mut self, short_code: NameShortCode) -> Self {
self.short_code = Some(StringValue::Parsed(short_code));
self
}
pub fn with_expected_confirmation_reference(mut self, reference: impl Into<String>) -> Self {
self.expected_confirmation_reference = Some(reference.into());
self
}
}
impl From<CandidateId> for CandidateIdentifier {
fn from(value: CandidateId) -> Self {
CandidateIdentifier::new(value)
}
}
impl EMLElement for CandidateIdentifier {
const EML_NAME: QualifiedName<'_, '_> =
QualifiedName::from_static("CandidateIdentifier", Some(NS_EML));
fn read_eml(elem: &mut EMLElementReader<'_, '_>) -> Result<Self, EMLError> {
let id = elem.string_value_attr("Id", None)?;
let display_order = elem.string_value_attr_opt("DisplayOrder")?;
let short_code = elem.string_value_attr_opt("ShortCode")?;
let expected_confirmation_reference = elem
.attribute_value("ExpectedConfirmationReference")?
.map(|s| s.into_owned());
struct CandidateIdentifierTmp {
short_code: Option<StringValue<NameShortCode>>,
}
let elem = collect_struct!(
elem,
CandidateIdentifierTmp {
short_code as Option: ("ShortCode", NS_EML) => |elem| elem.string_value()?,
}
);
Ok(CandidateIdentifier {
id,
display_order,
short_code: short_code.or(elem.short_code), expected_confirmation_reference,
})
}
fn write_eml(&self, writer: EMLElementWriter) -> Result<(), EMLError> {
writer
.attr("Id", &self.id.raw())?
.attr_opt("DisplayOrder", self.display_order.as_ref().map(|v| v.raw()))?
.attr_opt("ShortCode", self.short_code.as_ref().map(|v| v.raw()))?
.attr_opt(
"ExpectedConfirmationReference",
self.expected_confirmation_reference.as_ref(),
)?
.empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::io::{EMLParsingMode, EMLRead as _, test_write_eml_element, test_xml_fragment};
#[test]
fn test_simple_candidate_identifier() {
let xml = test_xml_fragment(
r#"
<CandidateIdentifier xmlns="urn:oasis:names:tc:evs:schema:eml" Id="1"/>
"#,
);
let can_id = CandidateIdentifier::parse_eml(&xml, EMLParsingMode::Strict).unwrap();
assert_eq!(
can_id.id,
StringValue::Parsed(CandidateId::new("1").unwrap())
);
assert_eq!(can_id.display_order, None);
assert_eq!(can_id.short_code, None);
assert_eq!(can_id.expected_confirmation_reference, None);
let xml_output = test_write_eml_element(&can_id, &[NS_EML]).unwrap();
assert_eq!(xml_output, xml);
}
#[test]
fn test_all_attributes_candidate_identifier() {
let xml = test_xml_fragment(
r#"
<CandidateIdentifier xmlns="urn:oasis:names:tc:evs:schema:eml" Id="2254" DisplayOrder="2" ShortCode="1234" ExpectedConfirmationReference="Ref123"/>
"#,
);
let can_id = CandidateIdentifier::parse_eml(&xml, EMLParsingMode::Strict).unwrap();
assert_eq!(
can_id.id,
StringValue::Parsed(CandidateId::new("2254").unwrap())
);
assert_eq!(
can_id.display_order,
Some(StringValue::Parsed(NonZeroU64::new(2).unwrap()))
);
assert_eq!(
can_id.short_code,
Some(StringValue::Parsed(NameShortCode::new("1234").unwrap()))
);
assert_eq!(
can_id.expected_confirmation_reference,
Some("Ref123".to_string())
);
let xml_output = test_write_eml_element(&can_id, &[NS_EML]).unwrap();
assert_eq!(xml_output, xml);
}
#[test]
fn test_candidate_identifier_construction() {
let can_id = CandidateIdentifier::new(CandidateId::new("5678").unwrap())
.with_display_order(NonZeroU64::new(3).unwrap())
.with_short_code(NameShortCode::new("9876").unwrap())
.with_expected_confirmation_reference("reference");
assert_eq!(
can_id.id,
StringValue::Parsed(CandidateId::new("5678").unwrap())
);
assert_eq!(
can_id.display_order,
Some(StringValue::Parsed(NonZeroU64::new(3).unwrap()))
);
assert_eq!(
can_id.short_code,
Some(StringValue::Parsed(NameShortCode::new("9876").unwrap()))
);
assert_eq!(
can_id.expected_confirmation_reference,
Some("reference".to_string())
);
}
}