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
use super::*;

#[derive(Serialize)]
pub struct DataContractWriter {
    namespace: String,
    class_name: String,
    table_name: String,
    items: Vec<XmlItem>,
}

#[derive(Serialize)]
pub struct XmlItem {
    is_vector: bool,
    fields: Vec<XmlField>,
}

#[derive(Serialize)]
pub struct XmlField {
    name: String,
    data: String,
}

impl DataContractWriter {
    pub fn new(namespace: &str, table: &XTable, table_suffix: &str) -> Self {
        Self {
            class_name: table.name.clone(),
            table_name: format!("{}{}", table.name, table_suffix),
            namespace: namespace.to_string(),
            items: table.as_xml(),
        }
    }
    pub fn write_xml(&self, output: &Path) -> XResult<()> {
        let ctx = Context::from_serialize(self)?;
        tera_render(include_str!("DataContract.xml.djv"), &ctx, output, "DataContract.xml")?;
        Ok(())
    }
}

impl XTable {
    fn as_xml(&self) -> Vec<XmlItem> {
        let headers = self.data.headers();
        self.data.rows().iter().map(|v| XmlItem { is_vector: false, fields: v.as_xml(&headers) }).collect()
    }
}

impl XDataItem {
    fn as_xml(&self, headers: &[&XCellHeader]) -> Vec<XmlField> {
        let mut out = vec![];

        for (i, datum) in self.data.iter().enumerate() {
            let field = match headers.get(i) {
                Some(s) => s.field_name.to_string(),
                None => break,
            };
            let data = match datum {
                XCellValue::Boolean(v) => v.to_string(),
                _ => datum.to_string(),
            };
            out.push(XmlField { name: field, data })
        }
        out.into_iter().sorted_by_key(|v| v.name.to_owned()).collect()
    }
}