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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
use std::io::Read;
use xml::reader::{EventReader, XmlEvent};

use super::*;
use crate::reader::{FromXML, ReaderError};

use std::str::FromStr;

impl FromXML for Numberings {
    fn from_xml<R: Read>(reader: R) -> Result<Self, ReaderError> {
        let mut parser = EventReader::new(reader);
        let mut nums = Self::default();
        loop {
            let e = parser.next();
            match e {
                Ok(XmlEvent::StartElement {
                    attributes, name, ..
                }) => {
                    let e = XMLElement::from_str(&name.local_name).unwrap();
                    match e {
                        XMLElement::AbstractNumbering => {
                            let mut id = 0;
                            for a in attributes {
                                let local_name = &a.name.local_name;
                                if local_name == "abstractNumId" {
                                    id = usize::from_str(&a.value)?;
                                }
                            }
                            let mut abs_num = AbstractNumbering::new(id);
                            loop {
                                let e = parser.next();
                                match e {
                                    Ok(XmlEvent::StartElement {
                                        attributes, name, ..
                                    }) => {
                                        let e = XMLElement::from_str(&name.local_name).unwrap();
                                        match e {
                                            XMLElement::Level => {
                                                let l = Level::read(&mut parser, &attributes)?;
                                                abs_num = abs_num.add_level(l);
                                            }
                                            XMLElement::StyleLink => {
                                                abs_num = abs_num.style_link(&attributes[0].value)
                                            }
                                            XMLElement::NumStyleLink => {
                                                abs_num =
                                                    abs_num.num_style_link(&attributes[0].value)
                                            }
                                            _ => {}
                                        }
                                    }
                                    Ok(XmlEvent::EndElement { name, .. }) => {
                                        let e = XMLElement::from_str(&name.local_name).unwrap();
                                        if let XMLElement::AbstractNumbering = e {
                                            nums = nums.add_abstract_numbering(abs_num);
                                            break;
                                        }
                                    }
                                    _ => {}
                                }
                            }
                            continue;
                        }
                        XMLElement::Num => {
                            let mut id = 0;
                            for a in attributes {
                                let local_name = &a.name.local_name;
                                if local_name == "numId" {
                                    id = usize::from_str(&a.value)?;
                                }
                            }
                            let mut abs_num_id = 0;
                            let mut level_overrides = vec![];

                            loop {
                                let e = parser.next();
                                match e {
                                    Ok(XmlEvent::StartElement {
                                        attributes, name, ..
                                    }) => {
                                        let e = XMLElement::from_str(&name.local_name).unwrap();
                                        match e {
                                            XMLElement::AbstractNumberingId => {
                                                abs_num_id = usize::from_str(&attributes[0].value)?
                                            }
                                            XMLElement::LvlOverride => {
                                                if let Ok(o) =
                                                    LevelOverride::read(&mut parser, &attributes)
                                                {
                                                    level_overrides.push(o);
                                                }
                                            }
                                            _ => {}
                                        }
                                    }
                                    Ok(XmlEvent::EndElement { name, .. }) => {
                                        let e = XMLElement::from_str(&name.local_name).unwrap();
                                        if let XMLElement::Num = e {
                                            let num = Numbering::new(id, abs_num_id);
                                            nums =
                                                nums.add_numbering(num.overrides(level_overrides));
                                            break;
                                        }
                                    }
                                    _ => {}
                                }
                            }
                            continue;
                        }
                        _ => {}
                    }
                }
                Ok(XmlEvent::EndElement { name, .. }) => {
                    let e = XMLElement::from_str(&name.local_name).unwrap();
                    if let XMLElement::Numbering = e {
                        break;
                    }
                }
                Ok(XmlEvent::EndDocument { .. }) => break,
                Err(_) => return Err(ReaderError::XMLReadError),
                _ => {}
            }
        }
        Ok(nums)
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use crate::types::*;
    #[cfg(test)]
    use pretty_assertions::assert_eq;

    #[test]
    fn test_numberings_from_xml() {
        let xml = r#"<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
            xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" >
    <w:abstractNum w:abstractNumId="0" w15:restartNumberingAfterBreak="0">
        <w:multiLevelType w:val="hybridMultilevel"></w:multiLevelType>
        <w:lvl w:ilvl="0" w15:tentative="1">
            <w:start w:val="1"></w:start>
            <w:numFmt w:val="bullet"></w:numFmt>
            <w:lvlText w:val="●"></w:lvlText>
            <w:lvlJc w:val="left"></w:lvlJc>
            <w:pPr>
                <w:ind w:left="720" w:hanging="360"></w:ind>
            </w:pPr>
            <w:rPr></w:rPr>
        </w:lvl>
    </w:abstractNum>
    <w:num w:numId="1">
        <w:abstractNumId w:val="0"></w:abstractNumId>
    </w:num>
</w:numbering>"#;
        let n = Numberings::from_xml(xml.as_bytes()).unwrap();
        let mut nums = Numberings::new();
        nums = nums
            .add_abstract_numbering(
                AbstractNumbering::new(0).add_level(
                    Level::new(
                        0,
                        Start::new(1),
                        NumberFormat::new("bullet"),
                        LevelText::new("●"),
                        LevelJc::new("left"),
                    )
                    .indent(
                        Some(720),
                        Some(SpecialIndentType::Hanging(360)),
                        None,
                        None,
                    ),
                ),
            )
            .add_numbering(Numbering::new(1, 0));
        assert_eq!(n, nums)
    }

    #[test]
    fn test_numberings_from_xml_with_num_style_link() {
        let xml = r#"<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
            xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" >
    <w:abstractNum w:abstractNumId="0">
        <w:multiLevelType w:val="hybridMultilevel"/>
        <w:numStyleLink w:val="style1"/>
    </w:abstractNum>
    <w:num w:numId="1">
        <w:abstractNumId w:val="0"></w:abstractNumId>
    </w:num>
</w:numbering>"#;
        let n = Numberings::from_xml(xml.as_bytes()).unwrap();
        let mut nums = Numberings::new();
        nums = nums
            .add_abstract_numbering(AbstractNumbering::new(0).num_style_link("style1"))
            .add_numbering(Numbering::new(1, 0));
        assert_eq!(n, nums)
    }

    #[test]
    fn test_numberings_from_xml_with_style_link() {
        let xml = r#"<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
            xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" >
    <w:abstractNum w:abstractNumId="0">
        <w:multiLevelType w:val="hybridMultilevel"/>
        <w:styleLink w:val="style1"/>
    </w:abstractNum>
    <w:num w:numId="1">
        <w:abstractNumId w:val="0"></w:abstractNumId>
    </w:num>
</w:numbering>"#;
        let n = Numberings::from_xml(xml.as_bytes()).unwrap();
        let mut nums = Numberings::new();
        nums = nums
            .add_abstract_numbering(AbstractNumbering::new(0).style_link("style1"))
            .add_numbering(Numbering::new(1, 0));
        assert_eq!(n, nums)
    }

    #[test]
    fn test_numberings_from_xml_with_override() {
        let xml = r#"<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
            xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" >
    <w:abstractNum w:abstractNumId="0">
        <w:multiLevelType w:val="hybridMultilevel"/>
    </w:abstractNum>
    <w:num w:numId="1">
        <w:abstractNumId w:val="0"></w:abstractNumId>
        <w:lvlOverride w:ilvl="0">
          <w:startOverride w:val="1"/>
        </w:lvlOverride>
        <w:lvlOverride w:ilvl="1">
          <w:startOverride w:val="1"/>
        </w:lvlOverride>
    </w:num>
</w:numbering>"#;
        let n = Numberings::from_xml(xml.as_bytes()).unwrap();
        let mut nums = Numberings::new();
        let overrides = vec![
            LevelOverride::new(0).start(1),
            LevelOverride::new(1).start(1),
        ];
        let num = Numbering::new(1, 0).overrides(overrides);
        nums = nums
            .add_abstract_numbering(AbstractNumbering::new(0))
            .add_numbering(num);
        assert_eq!(n, nums)
    }
}