1#[cfg(not(feature = "python"))]
2#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
5pub struct Export {
6 #[serde(rename = "date")]
7 #[serde(alias = "@date")]
8 #[serde(alias = "date")]
9 #[serde(
10 default,
11 deserialize_with = "deserialize_empty_string_as_none_datetime"
12 )]
13 pub date: Option<DateTime<Utc>>,
14
15 #[serde(rename = "createdBy")]
16 #[serde(alias = "@createdBy")]
17 #[serde(alias = "createdBy")]
18 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
19 pub created_by: Option<String>,
20
21 #[serde(rename = "role")]
22 #[serde(alias = "@role")]
23 #[serde(alias = "role")]
24 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
25 pub role: Option<String>,
26
27 #[serde(rename = "numberSubjectsProcessed")]
28 #[serde(alias = "@numberSubjectsProcessed")]
29 #[serde(alias = "numberSubjectsProcessed")]
30 #[serde(default)]
31 pub number_subjects_processed: Option<usize>,
32
33 #[serde(rename = "pageNumber")]
35 #[serde(alias = "@pageNumber")]
36 #[serde(alias = "pageNumber")]
37 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
38 pub page_number: Option<String>,
39}
40
41#[cfg(feature = "python")]
42#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
45#[pyclass(skip_from_py_object)]
46pub struct Export {
47 #[serde(rename = "date")]
48 #[serde(alias = "@date")]
49 #[serde(alias = "date")]
50 #[serde(
51 default,
52 deserialize_with = "deserialize_empty_string_as_none_datetime"
53 )]
54 pub date: Option<DateTime<Utc>>,
55
56 #[serde(rename = "createdBy")]
57 #[serde(alias = "@createdBy")]
58 #[serde(alias = "createdBy")]
59 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
60 pub created_by: Option<String>,
61
62 #[serde(rename = "role")]
63 #[serde(alias = "@role")]
64 #[serde(alias = "role")]
65 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
66 pub role: Option<String>,
67
68 #[serde(rename = "numberSubjectsProcessed")]
69 #[serde(alias = "@numberSubjectsProcessed")]
70 #[serde(alias = "numberSubjectsProcessed")]
71 #[serde(default)]
72 pub number_subjects_processed: Option<usize>,
73
74 #[serde(rename = "pageNumber")]
76 #[serde(alias = "@pageNumber")]
77 #[serde(alias = "pageNumber")]
78 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
79 pub page_number: Option<String>,
80}
81
82use std::sync::Arc;
83
84use chrono::{DateTime, Utc};
85use serde::{Deserialize, Serialize};
86
87#[cfg(feature = "python")]
88use pyo3::{
89 prelude::*,
90 types::{PyDateTime, PyDict},
91};
92
93use quick_xml::events::BytesStart;
94
95use crate::native::deserializers::{
96 attribute_string, checked_datetime, deserialize_empty_string_as_none,
97 deserialize_empty_string_as_none_arc, deserialize_empty_string_as_none_datetime,
98 optional_datetime, optional_string, visit_attributes, Interner,
99};
100
101#[cfg(feature = "python")]
102use crate::native::deserializers::{to_py_datetime, to_py_datetime_option};
103
104#[cfg(not(feature = "python"))]
105#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
106pub struct Value {
107 #[serde(rename = "by")]
108 #[serde(alias = "@by")]
109 #[serde(alias = "by")]
110 pub by: Arc<str>,
111
112 #[serde(rename = "byUniqueId")]
113 #[serde(alias = "@byUniqueId")]
114 #[serde(alias = "byUniqueId")]
115 #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
116 pub by_unique_id: Option<Arc<str>>,
117 #[serde(rename = "role")]
118 #[serde(alias = "@role")]
119 #[serde(alias = "role")]
120 pub role: Arc<str>,
121 #[serde(rename = "when")]
122 #[serde(alias = "@when")]
123 #[serde(alias = "when")]
124 pub when: Option<DateTime<Utc>>,
125
126 #[serde(rename = "value")]
127 #[serde(alias = "$text")]
128 #[serde(alias = "#text")]
129 #[serde(alias = "value")]
130 #[serde(default)]
131 pub value: String,
132}
133
134#[cfg(feature = "python")]
135#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
136#[pyclass(skip_from_py_object)]
137pub struct Value {
138 #[serde(rename = "by")]
139 #[serde(alias = "@by")]
140 #[serde(alias = "by")]
141 pub by: Arc<str>,
142
143 #[serde(rename = "byUniqueId")]
144 #[serde(alias = "@byUniqueId")]
145 #[serde(alias = "byUniqueId")]
146 #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
147 pub by_unique_id: Option<Arc<str>>,
148 #[serde(rename = "role")]
149 #[serde(alias = "@role")]
150 #[serde(alias = "role")]
151 pub role: Arc<str>,
152 #[serde(rename = "when")]
153 #[serde(alias = "@when")]
154 #[serde(alias = "when")]
155 pub when: Option<DateTime<Utc>>,
156
157 #[serde(rename = "value")]
158 #[serde(alias = "$text")]
159 #[serde(alias = "#text")]
160 #[serde(alias = "value")]
161 #[serde(default)]
162 pub value: String,
163}
164
165#[cfg(feature = "python")]
166#[pymethods]
167impl Value {
168 #[getter]
169 fn by(&self) -> PyResult<String> {
170 Ok(self.by.to_string())
171 }
172
173 #[getter]
174 fn by_unique_id(&self) -> PyResult<Option<String>> {
175 Ok(self.by_unique_id.as_deref().map(str::to_string))
176 }
177
178 #[getter]
179 fn role(&self) -> PyResult<String> {
180 Ok(self.role.to_string())
181 }
182
183 #[getter]
184 fn when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
185 to_py_datetime_option(py, &self.when)
186 }
187
188 #[getter]
189 fn value(&self) -> PyResult<String> {
190 Ok(self.value.clone())
191 }
192
193 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
194 let dict = PyDict::new(py);
195 dict.set_item("by", &*self.by)?;
196 dict.set_item("by_unique_id", self.by_unique_id.as_deref())?;
197 dict.set_item("role", &*self.role)?;
198 dict.set_item("when", to_py_datetime_option(py, &self.when)?)?;
199 dict.set_item("value", &self.value)?;
200
201 Ok(dict)
202 }
203}
204
205#[cfg(not(feature = "python"))]
206#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
207pub struct Reason {
208 #[serde(rename = "by")]
209 #[serde(alias = "@by")]
210 #[serde(alias = "by")]
211 pub by: Arc<str>,
212
213 #[serde(rename = "byUniqueId")]
214 #[serde(alias = "@byUniqueId")]
215 #[serde(alias = "byUniqueId")]
216 #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
217 pub by_unique_id: Option<Arc<str>>,
218
219 #[serde(rename = "role")]
220 #[serde(alias = "@role")]
221 #[serde(alias = "role")]
222 pub role: Arc<str>,
223 #[serde(rename = "when")]
224 #[serde(alias = "@when")]
225 #[serde(alias = "when")]
226 pub when: Option<DateTime<Utc>>,
227
228 #[serde(rename = "value")]
229 #[serde(alias = "$text")]
230 #[serde(alias = "#text")]
231 #[serde(alias = "value")]
232 #[serde(default)]
233 pub value: String,
234}
235
236#[cfg(feature = "python")]
237#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
238#[pyclass(skip_from_py_object)]
239pub struct Reason {
240 #[serde(rename = "by")]
241 #[serde(alias = "@by")]
242 #[serde(alias = "by")]
243 pub by: Arc<str>,
244
245 #[serde(rename = "byUniqueId")]
246 #[serde(alias = "@byUniqueId")]
247 #[serde(alias = "byUniqueId")]
248 #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
249 pub by_unique_id: Option<Arc<str>>,
250
251 #[serde(rename = "role")]
252 #[serde(alias = "@role")]
253 #[serde(alias = "role")]
254 pub role: Arc<str>,
255 #[serde(rename = "when")]
256 #[serde(alias = "@when")]
257 #[serde(alias = "when")]
258 pub when: Option<DateTime<Utc>>,
259
260 #[serde(rename = "value")]
261 #[serde(alias = "$text")]
262 #[serde(alias = "#text")]
263 #[serde(alias = "value")]
264 #[serde(default)]
265 pub value: String,
266}
267
268#[cfg(feature = "python")]
269#[pymethods]
270impl Reason {
271 #[getter]
272 fn by(&self) -> PyResult<String> {
273 Ok(self.by.to_string())
274 }
275
276 #[getter]
277 fn by_unique_id(&self) -> PyResult<Option<String>> {
278 Ok(self.by_unique_id.as_deref().map(str::to_string))
279 }
280
281 #[getter]
282 fn role(&self) -> PyResult<String> {
283 Ok(self.role.to_string())
284 }
285
286 #[getter]
287 fn when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
288 to_py_datetime_option(py, &self.when)
289 }
290
291 #[getter]
292 fn value(&self) -> PyResult<String> {
293 Ok(self.value.clone())
294 }
295
296 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
297 let dict = PyDict::new(py);
298 dict.set_item("by", &*self.by)?;
299 dict.set_item("by_unique_id", self.by_unique_id.as_deref())?;
300 dict.set_item("role", &*self.role)?;
301 dict.set_item("when", to_py_datetime_option(py, &self.when)?)?;
302 dict.set_item("value", &self.value)?;
303
304 Ok(dict)
305 }
306}
307
308#[cfg(not(feature = "python"))]
309#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
310pub struct Entry {
311 #[serde(rename = "entryId")]
312 #[serde(alias = "@id")]
313 #[serde(alias = "entryId")]
314 pub entry_id: Arc<str>,
315
316 #[serde(rename = "reviewedBy")]
317 #[serde(alias = "@reviewedBy")]
318 #[serde(alias = "reviewedBy")]
319 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
320 pub reviewed_by: Option<String>,
321
322 #[serde(rename = "reviewedByUniqueId")]
323 #[serde(alias = "@reviewedByUniqueId")]
324 #[serde(alias = "reviewedByUniqueId")]
325 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
326 pub reviewed_by_unique_id: Option<String>,
327
328 #[serde(rename = "reviewedByWhen")]
329 #[serde(alias = "@reviewedByWhen")]
330 #[serde(alias = "reviewedByWhen")]
331 #[serde(
332 default,
333 deserialize_with = "deserialize_empty_string_as_none_datetime"
334 )]
335 pub reviewed_by_when: Option<DateTime<Utc>>,
336
337 pub value: Option<Value>,
338 pub reason: Option<Reason>,
339}
340
341#[cfg(feature = "python")]
342#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
343#[pyclass(skip_from_py_object)]
344pub struct Entry {
345 #[serde(rename = "entryId")]
346 #[serde(alias = "@id")]
347 #[serde(alias = "entryId")]
348 pub entry_id: Arc<str>,
349
350 #[serde(rename = "reviewedBy")]
351 #[serde(alias = "@reviewedBy")]
352 #[serde(alias = "reviewedBy")]
353 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
354 pub reviewed_by: Option<String>,
355
356 #[serde(rename = "reviewedByUniqueId")]
357 #[serde(alias = "@reviewedByUniqueId")]
358 #[serde(alias = "reviewedByUniqueId")]
359 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
360 pub reviewed_by_unique_id: Option<String>,
361
362 #[serde(rename = "reviewedByWhen")]
363 #[serde(alias = "@reviewedByWhen")]
364 #[serde(alias = "reviewedByWhen")]
365 #[serde(
366 default,
367 deserialize_with = "deserialize_empty_string_as_none_datetime"
368 )]
369 pub reviewed_by_when: Option<DateTime<Utc>>,
370
371 pub value: Option<Value>,
372 pub reason: Option<Reason>,
373}
374
375#[cfg(feature = "python")]
376#[pymethods]
377impl Entry {
378 #[getter]
379 fn entry_id(&self) -> PyResult<String> {
380 Ok(self.entry_id.to_string())
381 }
382
383 #[getter]
384 fn reviewed_by(&self) -> PyResult<Option<String>> {
385 Ok(self.reviewed_by.clone())
386 }
387
388 #[getter]
389 fn reviewed_by_unique_id(&self) -> PyResult<Option<String>> {
390 Ok(self.reviewed_by_unique_id.clone())
391 }
392
393 #[getter]
394 fn reviewed_by_when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
395 to_py_datetime_option(py, &self.reviewed_by_when)
396 }
397
398 #[getter]
399 fn value(&self) -> PyResult<Option<Value>> {
400 Ok(self.value.clone())
401 }
402
403 #[getter]
404 fn reason(&self) -> PyResult<Option<Reason>> {
405 Ok(self.reason.clone())
406 }
407
408 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
409 let dict = PyDict::new(py);
410 dict.set_item("entry_id", &*self.entry_id)?;
411 dict.set_item("reviewed_by", &self.reviewed_by)?;
412 dict.set_item("reviewed_by_unique_id", &self.reviewed_by_unique_id)?;
413 dict.set_item(
414 "reviewed_by_when",
415 to_py_datetime_option(py, &self.reviewed_by_when)?,
416 )?;
417 if let Some(value) = &self.value {
418 dict.set_item("value", value.to_dict(py)?)?;
419 } else {
420 dict.set_item("value", py.None())?;
421 }
422 if let Some(reason) = &self.reason {
423 dict.set_item("reason", reason.to_dict(py)?)?;
424 } else {
425 dict.set_item("reason", py.None())?;
426 }
427
428 Ok(dict)
429 }
430}
431
432#[cfg(not(feature = "python"))]
433#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
434pub struct Comment {
435 #[serde(rename = "commentId")]
436 #[serde(alias = "@id")]
437 #[serde(alias = "commentId")]
438 pub comment_id: String,
439
440 #[serde(rename = "reviewedBy")]
441 #[serde(alias = "@reviewedBy")]
442 #[serde(alias = "reviewedBy")]
443 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
444 pub reviewed_by: Option<String>,
445
446 #[serde(rename = "reviewedByUniqueId")]
447 #[serde(alias = "@reviewedByUniqueId")]
448 #[serde(alias = "reviewedByUniqueId")]
449 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
450 pub reviewed_by_unique_id: Option<String>,
451
452 #[serde(rename = "reviewedByWhen")]
453 #[serde(alias = "@reviewedByWhen")]
454 #[serde(alias = "reviewedByWhen")]
455 #[serde(
456 default,
457 deserialize_with = "deserialize_empty_string_as_none_datetime"
458 )]
459 pub reviewed_by_when: Option<DateTime<Utc>>,
460
461 pub value: Option<Value>,
462}
463
464#[cfg(feature = "python")]
465#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
466#[pyclass(skip_from_py_object)]
467pub struct Comment {
468 #[serde(rename = "commentId")]
469 #[serde(alias = "@id")]
470 #[serde(alias = "commentId")]
471 pub comment_id: String,
472
473 #[serde(rename = "reviewedBy")]
474 #[serde(alias = "@reviewedBy")]
475 #[serde(alias = "reviewedBy")]
476 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
477 pub reviewed_by: Option<String>,
478
479 #[serde(rename = "reviewedByUniqueId")]
480 #[serde(alias = "@reviewedByUniqueId")]
481 #[serde(alias = "reviewedByUniqueId")]
482 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
483 pub reviewed_by_unique_id: Option<String>,
484
485 #[serde(rename = "reviewedByWhen")]
486 #[serde(alias = "@reviewedByWhen")]
487 #[serde(alias = "reviewedByWhen")]
488 #[serde(
489 default,
490 deserialize_with = "deserialize_empty_string_as_none_datetime"
491 )]
492 pub reviewed_by_when: Option<DateTime<Utc>>,
493
494 pub value: Option<Value>,
495}
496
497#[cfg(feature = "python")]
498#[pymethods]
499impl Query {
500 #[getter]
501 fn query_id(&self) -> PyResult<String> {
502 Ok(self.query_id.to_string())
503 }
504
505 #[getter]
506 fn reviewed_by(&self) -> PyResult<Option<String>> {
507 Ok(self.reviewed_by.clone())
508 }
509
510 #[getter]
511 fn reviewed_by_unique_id(&self) -> PyResult<Option<String>> {
512 Ok(self.reviewed_by_unique_id.clone())
513 }
514
515 #[getter]
516 fn reviewed_by_when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
517 to_py_datetime_option(py, &self.reviewed_by_when)
518 }
519
520 #[getter]
521 fn value(&self) -> PyResult<Option<Value>> {
522 Ok(self.value.clone())
523 }
524
525 #[getter]
526 fn answer(&self) -> PyResult<Option<Value>> {
527 Ok(self.answer.clone())
528 }
529
530 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
531 let dict = PyDict::new(py);
532 dict.set_item("query_id", &*self.query_id)?;
533 dict.set_item("reviewed_by", &self.reviewed_by)?;
534 dict.set_item("reviewed_by_unique_id", &self.reviewed_by_unique_id)?;
535 dict.set_item(
536 "reviewed_by_when",
537 to_py_datetime_option(py, &self.reviewed_by_when)?,
538 )?;
539
540 match &self.value {
541 Some(value) => dict.set_item("value", value.to_dict(py)?)?,
542 None => dict.set_item("value", py.None())?,
543 }
544
545 match &self.answer {
546 Some(answer) => dict.set_item("answer", answer.to_dict(py)?)?,
547 None => dict.set_item("answer", py.None())?,
548 }
549
550 Ok(dict)
551 }
552}
553
554#[cfg(feature = "python")]
555#[pymethods]
556impl File {
557 #[getter]
558 fn name(&self) -> PyResult<String> {
559 Ok(self.name.to_string())
560 }
561
562 #[getter]
563 fn file_type(&self) -> PyResult<String> {
564 Ok(self.file_type.to_string())
565 }
566
567 #[getter]
568 fn data_type(&self) -> PyResult<Option<String>> {
569 Ok(self.data_type.as_deref().map(str::to_string))
570 }
571
572 #[getter]
573 fn error_code(&self) -> PyResult<String> {
574 Ok(self.error_code.to_string())
575 }
576
577 #[getter]
578 fn when_created<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
579 to_py_datetime_option(py, &self.when_created)
580 }
581
582 #[getter]
583 fn keep_history(&self) -> PyResult<bool> {
584 Ok(self.keep_history)
585 }
586
587 #[getter]
588 fn file_location(&self) -> PyResult<Option<String>> {
589 Ok(self.file_location.clone())
590 }
591
592 #[getter]
593 fn size(&self) -> PyResult<Option<usize>> {
594 Ok(self.size)
595 }
596
597 #[getter]
598 fn entries(&self) -> PyResult<Option<Vec<Entry>>> {
599 Ok(self.entries.as_deref().cloned())
600 }
601
602 #[getter]
603 fn comments(&self) -> PyResult<Option<Vec<Comment>>> {
604 Ok(self.comments.as_deref().cloned())
605 }
606
607 #[getter]
608 fn queries(&self) -> PyResult<Option<Vec<Query>>> {
609 Ok(self.queries.as_deref().cloned())
610 }
611
612 #[getter]
613 fn download_history(&self) -> PyResult<Option<Vec<Comment>>> {
614 Ok(self.download_history.as_deref().cloned())
615 }
616
617 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
618 let dict = PyDict::new(py);
619 dict.set_item("name", &*self.name)?;
620 dict.set_item("file_type", &*self.file_type)?;
621 dict.set_item("data_type", self.data_type.as_deref())?;
622 dict.set_item("error_code", &*self.error_code)?;
623 dict.set_item(
624 "when_created",
625 to_py_datetime_option(py, &self.when_created)?,
626 )?;
627 dict.set_item("keep_history", self.keep_history)?;
628 dict.set_item("file_location", &self.file_location)?;
629 dict.set_item("size", self.size)?;
630
631 for (key, items) in [(
632 "entries",
633 self.entries.as_deref().map(|v| {
634 v.iter()
635 .map(|x| x.to_dict(py))
636 .collect::<PyResult<Vec<_>>>()
637 }),
638 )] {
639 match items {
640 Some(items) => dict.set_item(key, items?)?,
641 None => dict.set_item(key, py.None())?,
642 }
643 }
644
645 match self.comments.as_deref() {
646 Some(items) => dict.set_item(
647 "comments",
648 items
649 .iter()
650 .map(|x| x.to_dict(py))
651 .collect::<PyResult<Vec<_>>>()?,
652 )?,
653 None => dict.set_item("comments", py.None())?,
654 }
655
656 match self.queries.as_deref() {
657 Some(items) => dict.set_item(
658 "queries",
659 items
660 .iter()
661 .map(|x| x.to_dict(py))
662 .collect::<PyResult<Vec<_>>>()?,
663 )?,
664 None => dict.set_item("queries", py.None())?,
665 }
666
667 match self.download_history.as_deref() {
668 Some(items) => dict.set_item(
669 "download_history",
670 items
671 .iter()
672 .map(|x| x.to_dict(py))
673 .collect::<PyResult<Vec<_>>>()?,
674 )?,
675 None => dict.set_item("download_history", py.None())?,
676 }
677
678 Ok(dict)
679 }
680}
681
682#[cfg(feature = "python")]
683#[pymethods]
684impl Comment {
685 #[getter]
686 fn comment_id(&self) -> PyResult<String> {
687 Ok(self.comment_id.clone())
688 }
689
690 #[getter]
691 fn value(&self) -> PyResult<Option<Value>> {
692 Ok(self.value.clone())
693 }
694
695 #[getter]
696 fn reviewed_by(&self) -> PyResult<Option<String>> {
697 Ok(self.reviewed_by.clone())
698 }
699
700 #[getter]
701 fn reviewed_by_unique_id(&self) -> PyResult<Option<String>> {
702 Ok(self.reviewed_by_unique_id.clone())
703 }
704
705 #[getter]
706 fn reviewed_by_when<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
707 to_py_datetime_option(py, &self.reviewed_by_when)
708 }
709
710 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
711 let dict = PyDict::new(py);
712 dict.set_item("comment_id", &self.comment_id)?;
713 dict.set_item("reviewed_by", &self.reviewed_by)?;
714 dict.set_item("reviewed_by_unique_id", &self.reviewed_by_unique_id)?;
715 dict.set_item(
716 "reviewed_by_when",
717 to_py_datetime_option(py, &self.reviewed_by_when)?,
718 )?;
719 if let Some(value) = &self.value {
720 dict.set_item("value", value.to_dict(py)?)?;
721 } else {
722 dict.set_item("value", py.None())?;
723 }
724
725 Ok(dict)
726 }
727}
728
729#[cfg(not(feature = "python"))]
730#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
731pub struct Query {
732 #[serde(rename = "queryId")]
733 #[serde(alias = "@id")]
734 #[serde(alias = "queryId")]
735 pub query_id: Arc<str>,
736
737 #[serde(rename = "reviewedBy")]
738 #[serde(alias = "@reviewedBy")]
739 #[serde(alias = "reviewedBy")]
740 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
741 pub reviewed_by: Option<String>,
742
743 #[serde(rename = "reviewedByUniqueId")]
744 #[serde(alias = "@reviewedByUniqueId")]
745 #[serde(alias = "reviewedByUniqueId")]
746 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
747 pub reviewed_by_unique_id: Option<String>,
748
749 #[serde(rename = "reviewedByWhen")]
750 #[serde(alias = "@reviewedByWhen")]
751 #[serde(alias = "reviewedByWhen")]
752 #[serde(
753 default,
754 deserialize_with = "deserialize_empty_string_as_none_datetime"
755 )]
756 pub reviewed_by_when: Option<DateTime<Utc>>,
757
758 pub value: Option<Value>,
759 pub answer: Option<Value>,
760}
761
762#[cfg(not(feature = "python"))]
763#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
764pub struct File {
765 #[serde(rename = "name")]
766 #[serde(alias = "@name")]
767 #[serde(alias = "name")]
768 pub name: Arc<str>,
769
770 #[serde(rename = "fileType")]
771 #[serde(alias = "@type")]
772 #[serde(alias = "fileType")]
773 pub file_type: Arc<str>,
774
775 #[serde(rename = "dataType")]
776 #[serde(alias = "@dataType")]
777 #[serde(alias = "dataType")]
778 #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
779 pub data_type: Option<Arc<str>>,
780
781 #[serde(rename = "errorCode")]
782 #[serde(alias = "@errorCode")]
783 #[serde(alias = "errorCode")]
784 pub error_code: Arc<str>,
785
786 #[serde(rename = "whenCreated")]
787 #[serde(alias = "@whenCreated")]
788 #[serde(alias = "whenCreated")]
789 pub when_created: Option<DateTime<Utc>>,
790
791 #[serde(rename = "keepHistory")]
792 #[serde(alias = "@keepHistory")]
793 #[serde(alias = "keepHistory")]
794 pub keep_history: bool,
795
796 #[serde(rename = "fileLocation")]
797 #[serde(alias = "@fileLocation")]
798 #[serde(alias = "fileLocation")]
799 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
800 pub file_location: Option<String>,
801
802 #[serde(rename = "size")]
803 #[serde(alias = "@size")]
804 #[serde(alias = "size")]
805 #[serde(default)]
806 pub size: Option<usize>,
807
808 #[serde(alias = "entry")]
809 pub entries: Option<Arc<Vec<Entry>>>,
810
811 #[serde(alias = "comment")]
812 pub comments: Option<Arc<Vec<Comment>>>,
813
814 #[serde(alias = "query")]
815 pub queries: Option<Arc<Vec<Query>>>,
816
817 #[serde(rename = "downloadHistory")]
818 #[serde(alias = "downloadHistory")]
819 pub download_history: Option<Arc<Vec<Comment>>>,
820}
821
822#[cfg(feature = "python")]
823#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
824#[pyclass(skip_from_py_object)]
825pub struct Query {
826 #[serde(rename = "queryId")]
827 #[serde(alias = "@id")]
828 #[serde(alias = "queryId")]
829 pub query_id: Arc<str>,
830
831 #[serde(rename = "reviewedBy")]
832 #[serde(alias = "@reviewedBy")]
833 #[serde(alias = "reviewedBy")]
834 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
835 pub reviewed_by: Option<String>,
836
837 #[serde(rename = "reviewedByUniqueId")]
838 #[serde(alias = "@reviewedByUniqueId")]
839 #[serde(alias = "reviewedByUniqueId")]
840 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
841 pub reviewed_by_unique_id: Option<String>,
842
843 #[serde(rename = "reviewedByWhen")]
844 #[serde(alias = "@reviewedByWhen")]
845 #[serde(alias = "reviewedByWhen")]
846 #[serde(
847 default,
848 deserialize_with = "deserialize_empty_string_as_none_datetime"
849 )]
850 pub reviewed_by_when: Option<DateTime<Utc>>,
851
852 pub value: Option<Value>,
853 pub answer: Option<Value>,
854}
855
856#[cfg(feature = "python")]
857#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
858#[pyclass(skip_from_py_object)]
859pub struct File {
860 #[serde(rename = "name")]
861 #[serde(alias = "@name")]
862 #[serde(alias = "name")]
863 pub name: Arc<str>,
864
865 #[serde(rename = "fileType")]
866 #[serde(alias = "@type")]
867 #[serde(alias = "fileType")]
868 pub file_type: Arc<str>,
869
870 #[serde(rename = "dataType")]
871 #[serde(alias = "@dataType")]
872 #[serde(alias = "dataType")]
873 #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
874 pub data_type: Option<Arc<str>>,
875
876 #[serde(rename = "errorCode")]
877 #[serde(alias = "@errorCode")]
878 #[serde(alias = "errorCode")]
879 pub error_code: Arc<str>,
880
881 #[serde(rename = "whenCreated")]
882 #[serde(alias = "@whenCreated")]
883 #[serde(alias = "whenCreated")]
884 pub when_created: Option<DateTime<Utc>>,
885
886 #[serde(rename = "keepHistory")]
887 #[serde(alias = "@keepHistory")]
888 #[serde(alias = "keepHistory")]
889 pub keep_history: bool,
890
891 #[serde(rename = "fileLocation")]
892 #[serde(alias = "@fileLocation")]
893 #[serde(alias = "fileLocation")]
894 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
895 pub file_location: Option<String>,
896
897 #[serde(rename = "size")]
898 #[serde(alias = "@size")]
899 #[serde(alias = "size")]
900 #[serde(default)]
901 pub size: Option<usize>,
902
903 #[serde(alias = "entry")]
904 pub entries: Option<Arc<Vec<Entry>>>,
905
906 #[serde(alias = "comment")]
907 pub comments: Option<Arc<Vec<Comment>>>,
908
909 #[serde(alias = "query")]
910 pub queries: Option<Arc<Vec<Query>>>,
911
912 #[serde(rename = "downloadHistory")]
913 #[serde(alias = "downloadHistory")]
914 pub download_history: Option<Arc<Vec<Comment>>>,
915}
916
917#[cfg(not(feature = "python"))]
918#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
919pub struct Field {
920 #[serde(rename = "name")]
921 #[serde(alias = "@name")]
922 #[serde(alias = "name")]
923 pub name: Arc<str>,
924
925 #[serde(rename = "fieldType")]
926 #[serde(alias = "@type")]
927 #[serde(alias = "fieldType")]
928 pub field_type: Arc<str>,
929
930 #[serde(rename = "dataType")]
931 #[serde(alias = "@dataType")]
932 #[serde(alias = "dataType")]
933 #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
934 pub data_type: Option<Arc<str>>,
935 #[serde(rename = "errorCode")]
936 #[serde(alias = "@errorCode")]
937 #[serde(alias = "errorCode")]
938 pub error_code: Arc<str>,
939 #[serde(rename = "whenCreated")]
940 #[serde(alias = "@whenCreated")]
941 #[serde(alias = "whenCreated")]
942 pub when_created: Option<DateTime<Utc>>,
943 #[serde(rename = "keepHistory")]
944 #[serde(alias = "@keepHistory")]
945 #[serde(alias = "keepHistory")]
946 pub keep_history: bool,
947
948 #[serde(alias = "entry")]
949 pub entries: Option<Arc<Vec<Entry>>>,
950
951 #[serde(alias = "comment")]
952 pub comments: Option<Arc<Vec<Comment>>>,
953
954 #[serde(alias = "query")]
955 pub queries: Option<Arc<Vec<Query>>>,
956}
957
958#[cfg(feature = "python")]
959#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
960#[pyclass(skip_from_py_object)]
961pub struct Field {
962 #[serde(rename = "name")]
963 #[serde(alias = "@name")]
964 #[serde(alias = "name")]
965 pub name: Arc<str>,
966
967 #[serde(rename = "fieldType")]
968 #[serde(alias = "@type")]
969 #[serde(alias = "fieldType")]
970 pub field_type: Arc<str>,
971
972 #[serde(rename = "dataType")]
973 #[serde(alias = "@dataType")]
974 #[serde(alias = "dataType")]
975 #[serde(default, deserialize_with = "deserialize_empty_string_as_none_arc")]
976 pub data_type: Option<Arc<str>>,
977
978 #[serde(rename = "errorCode")]
979 #[serde(alias = "@errorCode")]
980 #[serde(alias = "errorCode")]
981 pub error_code: Arc<str>,
982 #[serde(rename = "whenCreated")]
983 #[serde(alias = "@whenCreated")]
984 #[serde(alias = "whenCreated")]
985 pub when_created: Option<DateTime<Utc>>,
986 #[serde(rename = "keepHistory")]
987 #[serde(alias = "@keepHistory")]
988 #[serde(alias = "keepHistory")]
989 pub keep_history: bool,
990
991 #[serde(alias = "entry")]
992 pub entries: Option<Arc<Vec<Entry>>>,
993
994 #[serde(alias = "comment")]
995 pub comments: Option<Arc<Vec<Comment>>>,
996
997 #[serde(alias = "query")]
998 pub queries: Option<Arc<Vec<Query>>>,
999}
1000
1001#[cfg(feature = "python")]
1002#[pymethods]
1003impl Field {
1004 #[getter]
1005 fn name(&self) -> PyResult<String> {
1006 Ok(self.name.to_string())
1007 }
1008
1009 #[getter]
1010 fn field_type(&self) -> PyResult<String> {
1011 Ok(self.field_type.to_string())
1012 }
1013
1014 #[getter]
1015 fn data_type(&self) -> PyResult<Option<String>> {
1016 Ok(self.data_type.as_deref().map(str::to_string))
1017 }
1018
1019 #[getter]
1020 fn error_code(&self) -> PyResult<String> {
1021 Ok(self.error_code.to_string())
1022 }
1023
1024 #[getter]
1025 fn when_created<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1026 self.when_created
1027 .as_ref()
1028 .map(|dt| to_py_datetime(py, dt))
1029 .transpose()
1030 }
1031
1032 #[getter]
1033 fn keep_history(&self) -> PyResult<bool> {
1034 Ok(self.keep_history)
1035 }
1036
1037 #[getter]
1038 fn entries(&self) -> PyResult<Option<Vec<Entry>>> {
1039 Ok(self.entries.as_deref().cloned())
1040 }
1041
1042 #[getter]
1043 fn comments(&self) -> PyResult<Option<Vec<Comment>>> {
1044 Ok(self.comments.as_deref().cloned())
1045 }
1046
1047 #[getter]
1048 fn queries(&self) -> PyResult<Option<Vec<Query>>> {
1049 Ok(self.queries.as_deref().cloned())
1050 }
1051
1052 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1053 let dict = PyDict::new(py);
1054 dict.set_item("name", &*self.name)?;
1055 dict.set_item("field_type", &*self.field_type)?;
1056 dict.set_item("data_type", self.data_type.as_deref())?;
1057 dict.set_item("error_code", &*self.error_code)?;
1058 dict.set_item(
1059 "when_created",
1060 self.when_created
1061 .as_ref()
1062 .map(|dt| to_py_datetime(py, dt))
1063 .transpose()?,
1064 )?;
1065 dict.set_item("keep_history", self.keep_history)?;
1066
1067 let mut entry_dicts = Vec::new();
1068 if let Some(entries) = &self.entries {
1069 for entry in entries.iter() {
1070 let entry_dict = entry.to_dict(py)?;
1071 entry_dicts.push(entry_dict);
1072 }
1073 dict.set_item("entries", entry_dicts)?;
1074 } else {
1075 dict.set_item("entries", py.None())?;
1076 }
1077
1078 let mut comment_dicts = Vec::new();
1079 if let Some(comments) = &self.comments {
1080 for comment in comments.iter() {
1081 let comment_dict = comment.to_dict(py)?;
1082 comment_dicts.push(comment_dict);
1083 }
1084 dict.set_item("comments", comment_dicts)?;
1085 } else {
1086 dict.set_item("comments", py.None())?;
1087 }
1088
1089 let mut queries_dicts = Vec::new();
1090 if let Some(queries) = &self.queries {
1091 for item in queries.iter() {
1092 queries_dicts.push(item.to_dict(py)?);
1093 }
1094 dict.set_item("queries", queries_dicts)?;
1095 } else {
1096 dict.set_item("queries", py.None())?;
1097 }
1098 Ok(dict)
1099 }
1100}
1101
1102#[cfg(not(feature = "python"))]
1103#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1104pub struct Category {
1105 #[serde(rename = "name")]
1106 #[serde(alias = "@name")]
1107 #[serde(alias = "name")]
1108 pub name: Arc<str>,
1109
1110 #[serde(rename = "categoryType")]
1111 #[serde(alias = "@type")]
1112 #[serde(alias = "categoryType")]
1113 pub category_type: Arc<str>,
1114
1115 #[serde(rename = "highestIndex")]
1116 #[serde(alias = "@highestIndex")]
1117 #[serde(alias = "highestIndex")]
1118 pub highest_index: usize,
1119
1120 #[serde(rename = "obfuscated")]
1121 #[serde(alias = "@obfuscated")]
1122 #[serde(alias = "obfuscated")]
1123 #[serde(default)]
1124 pub obfuscated: bool,
1125
1126 #[serde(rename = "overRideHighestIndex")]
1127 #[serde(alias = "@overRideHighestIndex")]
1128 #[serde(alias = "overRideHighestIndex")]
1129 #[serde(default)]
1130 pub over_ride_highest_index: bool,
1131
1132 #[serde(alias = "field")]
1133 pub fields: Option<Arc<Vec<Field>>>,
1134
1135 #[serde(alias = "file")]
1136 pub files: Option<Arc<Vec<File>>>,
1137}
1138
1139#[cfg(feature = "python")]
1140#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1141#[pyclass(skip_from_py_object)]
1142pub struct Category {
1143 #[serde(rename = "name")]
1144 #[serde(alias = "@name")]
1145 #[serde(alias = "name")]
1146 pub name: Arc<str>,
1147
1148 #[serde(rename = "categoryType")]
1149 #[serde(alias = "@type")]
1150 #[serde(alias = "categoryType")]
1151 pub category_type: Arc<str>,
1152
1153 #[serde(rename = "highestIndex")]
1154 #[serde(alias = "@highestIndex")]
1155 #[serde(alias = "highestIndex")]
1156 pub highest_index: usize,
1157
1158 #[serde(rename = "obfuscated")]
1159 #[serde(alias = "@obfuscated")]
1160 #[serde(alias = "obfuscated")]
1161 #[serde(default)]
1162 pub obfuscated: bool,
1163
1164 #[serde(rename = "overRideHighestIndex")]
1165 #[serde(alias = "@overRideHighestIndex")]
1166 #[serde(alias = "overRideHighestIndex")]
1167 #[serde(default)]
1168 pub over_ride_highest_index: bool,
1169
1170 #[serde(alias = "field")]
1171 pub fields: Option<Arc<Vec<Field>>>,
1172
1173 #[serde(alias = "file")]
1174 pub files: Option<Arc<Vec<File>>>,
1175}
1176
1177#[cfg(feature = "python")]
1178#[pymethods]
1179impl Category {
1180 #[getter]
1181 fn name(&self) -> PyResult<String> {
1182 Ok(self.name.to_string())
1183 }
1184
1185 #[getter]
1186 fn category_type(&self) -> PyResult<String> {
1187 Ok(self.category_type.to_string())
1188 }
1189
1190 #[getter]
1191 fn highest_index(&self) -> PyResult<usize> {
1192 Ok(self.highest_index)
1193 }
1194
1195 #[getter]
1196 fn fields(&self) -> PyResult<Option<Vec<Field>>> {
1197 Ok(self.fields.as_deref().cloned())
1198 }
1199
1200 #[getter]
1201 fn files(&self) -> PyResult<Option<Vec<File>>> {
1202 Ok(self.files.as_deref().cloned())
1203 }
1204
1205 #[getter]
1206 fn obfuscated(&self) -> PyResult<bool> {
1207 Ok(self.obfuscated)
1208 }
1209
1210 #[getter]
1211 fn over_ride_highest_index(&self) -> PyResult<bool> {
1212 Ok(self.over_ride_highest_index)
1213 }
1214
1215 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1216 let dict = PyDict::new(py);
1217 dict.set_item("name", &*self.name)?;
1218 dict.set_item("category_type", &*self.category_type)?;
1219 dict.set_item("highest_index", self.highest_index)?;
1220 dict.set_item("obfuscated", self.obfuscated)?;
1221 dict.set_item("over_ride_highest_index", self.over_ride_highest_index)?;
1222
1223 let mut field_dicts = Vec::new();
1224 if let Some(fields) = &self.fields {
1225 for field in fields.iter() {
1226 let field_dict = field.to_dict(py)?;
1227 field_dicts.push(field_dict);
1228 }
1229 dict.set_item("fields", field_dicts)?;
1230 } else {
1231 dict.set_item("fields", py.None())?;
1232 }
1233
1234 let mut files_dicts = Vec::new();
1235 if let Some(files) = &self.files {
1236 for item in files.iter() {
1237 files_dicts.push(item.to_dict(py)?);
1238 }
1239 dict.set_item("files", files_dicts)?;
1240 } else {
1241 dict.set_item("files", py.None())?;
1242 }
1243 Ok(dict)
1244 }
1245}
1246
1247impl Form {
1248 pub(crate) fn from_attributes(e: &BytesStart<'_>) -> Result<Self, crate::errors::Error> {
1249 let mut name = "";
1250 let mut last_modified = "";
1251 let mut who_last_modified_name = "";
1252 let mut who_last_modified_role = "";
1253 let mut when_created = "";
1254 let mut has_errors = "";
1255 let mut has_warnings = "";
1256 let mut locked = "";
1257 let mut user = "";
1258 let mut date_time_changed = "";
1259 let mut form_title = "";
1260 let mut form_index = "";
1261 let mut form_group = "";
1262 let mut form_state = "";
1263
1264 visit_attributes(e, |key, attr| match key {
1265 b"name" => name = attr,
1266 b"lastModified" => last_modified = attr,
1267 b"whoLastModifiedName" => who_last_modified_name = attr,
1268 b"whoLastModifiedRole" => who_last_modified_role = attr,
1269 b"whenCreated" => when_created = attr,
1270 b"hasErrors" => has_errors = attr,
1271 b"hasWarnings" => has_warnings = attr,
1272 b"locked" => locked = attr,
1273 b"user" => user = attr,
1274 b"dateTimeChanged" => date_time_changed = attr,
1275 b"formTitle" => form_title = attr,
1276 b"formIndex" => form_index = attr,
1277 b"formGroup" => form_group = attr,
1278 b"formState" => form_state = attr,
1279 _ => {}
1280 })?;
1281
1282 Ok(Form {
1283 name: attribute_string(name),
1284 last_modified: optional_datetime(last_modified),
1285 who_last_modified_name: optional_string(who_last_modified_name),
1286 who_last_modified_role: optional_string(who_last_modified_role),
1287 when_created: when_created.parse().unwrap_or(0),
1288 has_errors: has_errors == "true",
1289 has_warnings: has_warnings == "true",
1290 locked: locked == "true",
1291 user: optional_string(user),
1292 date_time_changed: optional_datetime(date_time_changed),
1293 form_title: attribute_string(form_title),
1294 form_index: form_index.parse().unwrap_or(0),
1295 form_group: optional_string(form_group),
1296 form_state: attribute_string(form_state),
1297 states: None,
1298 lock_states: None,
1299 categories: None,
1300 })
1301 }
1302}
1303
1304#[cfg(not(feature = "python"))]
1305#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1306pub struct State {
1307 #[serde(rename = "value")]
1308 #[serde(alias = "@value")]
1309 #[serde(alias = "value")]
1310 pub value: Arc<str>,
1311 #[serde(rename = "signer")]
1312 #[serde(alias = "@signer")]
1313 #[serde(alias = "signer")]
1314 pub signer: Arc<str>,
1315 #[serde(rename = "signerUniqueId")]
1316 #[serde(alias = "@signerUniqueId")]
1317 #[serde(alias = "signerUniqueId")]
1318 pub signer_unique_id: Arc<str>,
1319
1320 #[serde(rename = "dateSigned")]
1321 #[serde(alias = "@dateSigned")]
1322 #[serde(alias = "dateSigned")]
1323 #[serde(
1324 default,
1325 deserialize_with = "deserialize_empty_string_as_none_datetime"
1326 )]
1327 pub date_signed: Option<DateTime<Utc>>,
1328}
1329
1330#[cfg(feature = "python")]
1331#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1332#[pyclass(skip_from_py_object)]
1333pub struct State {
1334 #[serde(rename = "value")]
1335 #[serde(alias = "@value")]
1336 #[serde(alias = "value")]
1337 pub value: Arc<str>,
1338 #[serde(rename = "signer")]
1339 #[serde(alias = "@signer")]
1340 #[serde(alias = "signer")]
1341 pub signer: Arc<str>,
1342 #[serde(rename = "signerUniqueId")]
1343 #[serde(alias = "@signerUniqueId")]
1344 #[serde(alias = "signerUniqueId")]
1345 pub signer_unique_id: Arc<str>,
1346
1347 #[serde(rename = "dateSigned")]
1348 #[serde(alias = "@dateSigned")]
1349 #[serde(alias = "dateSigned")]
1350 #[serde(
1351 default,
1352 deserialize_with = "deserialize_empty_string_as_none_datetime"
1353 )]
1354 pub date_signed: Option<DateTime<Utc>>,
1355}
1356
1357#[cfg(feature = "python")]
1358#[pymethods]
1359impl State {
1360 #[getter]
1361 fn value(&self) -> PyResult<String> {
1362 Ok(self.value.to_string())
1363 }
1364
1365 #[getter]
1366 fn signer(&self) -> PyResult<String> {
1367 Ok(self.signer.to_string())
1368 }
1369
1370 #[getter]
1371 fn signer_unique_id(&self) -> PyResult<String> {
1372 Ok(self.signer_unique_id.to_string())
1373 }
1374
1375 #[getter]
1376 fn date_signed<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1377 to_py_datetime_option(py, &self.date_signed)
1378 }
1379
1380 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1381 let dict = PyDict::new(py);
1382 dict.set_item("value", &*self.value)?;
1383 dict.set_item("signer", &*self.signer)?;
1384 dict.set_item("signer_unique_id", &*self.signer_unique_id)?;
1385 dict.set_item("date_signed", to_py_datetime_option(py, &self.date_signed)?)?;
1386
1387 Ok(dict)
1388 }
1389}
1390
1391#[cfg(not(feature = "python"))]
1392#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1393pub struct LockState {
1394 #[serde(rename = "locked")]
1395 #[serde(alias = "@locked")]
1396 #[serde(alias = "locked")]
1397 pub locked: bool,
1398
1399 #[serde(rename = "user")]
1400 #[serde(alias = "@user")]
1401 #[serde(alias = "user")]
1402 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1403 pub user: Option<String>,
1404
1405 #[serde(rename = "userUniqueId")]
1406 #[serde(alias = "@userUniqueId")]
1407 #[serde(alias = "userUniqueId")]
1408 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1409 pub user_unique_id: Option<String>,
1410
1411 #[serde(rename = "dateTimeChanged")]
1412 #[serde(alias = "@dateTimeChanged")]
1413 #[serde(alias = "dateTimeChanged")]
1414 #[serde(
1415 default,
1416 deserialize_with = "deserialize_empty_string_as_none_datetime"
1417 )]
1418 pub date_time_changed: Option<DateTime<Utc>>,
1419}
1420
1421#[cfg(feature = "python")]
1422#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1423#[pyclass(skip_from_py_object)]
1424pub struct LockState {
1425 #[serde(rename = "locked")]
1426 #[serde(alias = "@locked")]
1427 #[serde(alias = "locked")]
1428 pub locked: bool,
1429
1430 #[serde(rename = "user")]
1431 #[serde(alias = "@user")]
1432 #[serde(alias = "user")]
1433 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1434 pub user: Option<String>,
1435
1436 #[serde(rename = "userUniqueId")]
1437 #[serde(alias = "@userUniqueId")]
1438 #[serde(alias = "userUniqueId")]
1439 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1440 pub user_unique_id: Option<String>,
1441
1442 #[serde(rename = "dateTimeChanged")]
1443 #[serde(alias = "@dateTimeChanged")]
1444 #[serde(alias = "dateTimeChanged")]
1445 #[serde(
1446 default,
1447 deserialize_with = "deserialize_empty_string_as_none_datetime"
1448 )]
1449 pub date_time_changed: Option<DateTime<Utc>>,
1450}
1451
1452#[cfg(feature = "python")]
1453#[pymethods]
1454impl LockState {
1455 #[getter]
1456 fn locked(&self) -> PyResult<bool> {
1457 Ok(self.locked)
1458 }
1459
1460 #[getter]
1461 fn user(&self) -> PyResult<Option<String>> {
1462 Ok(self.user.clone())
1463 }
1464
1465 #[getter]
1466 fn user_unique_id(&self) -> PyResult<Option<String>> {
1467 Ok(self.user_unique_id.clone())
1468 }
1469
1470 #[getter]
1471 fn date_time_changed<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1472 to_py_datetime_option(py, &self.date_time_changed)
1473 }
1474
1475 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1476 let dict = PyDict::new(py);
1477 dict.set_item("locked", self.locked)?;
1478 dict.set_item("user", &self.user)?;
1479 dict.set_item("user_unique_id", &self.user_unique_id)?;
1480 dict.set_item(
1481 "date_time_changed",
1482 to_py_datetime_option(py, &self.date_time_changed)?,
1483 )?;
1484
1485 Ok(dict)
1486 }
1487}
1488
1489#[cfg(not(feature = "python"))]
1490#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1491pub struct Form {
1492 #[serde(rename = "name")]
1493 #[serde(alias = "@name")]
1494 #[serde(alias = "name")]
1495 pub name: String,
1496
1497 #[serde(rename = "lastModified")]
1498 #[serde(alias = "@lastModified")]
1499 #[serde(alias = "lastModified")]
1500 #[serde(
1501 default,
1502 deserialize_with = "deserialize_empty_string_as_none_datetime"
1503 )]
1504 pub last_modified: Option<DateTime<Utc>>,
1505
1506 #[serde(rename = "whoLastModifiedName")]
1507 #[serde(alias = "@whoLastModifiedName")]
1508 #[serde(alias = "whoLastModifiedName")]
1509 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1510 pub who_last_modified_name: Option<String>,
1511
1512 #[serde(rename = "whoLastModifiedRole")]
1513 #[serde(alias = "@whoLastModifiedRole")]
1514 #[serde(alias = "whoLastModifiedRole")]
1515 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1516 pub who_last_modified_role: Option<String>,
1517
1518 #[serde(rename = "whenCreated")]
1519 #[serde(alias = "@whenCreated")]
1520 #[serde(alias = "whenCreated")]
1521 pub when_created: usize,
1522 #[serde(rename = "hasErrors")]
1523 #[serde(alias = "@hasErrors")]
1524 #[serde(alias = "hasErrors")]
1525 pub has_errors: bool,
1526 #[serde(rename = "hasWarnings")]
1527 #[serde(alias = "@hasWarnings")]
1528 #[serde(alias = "hasWarnings")]
1529 pub has_warnings: bool,
1530 #[serde(rename = "locked")]
1531 #[serde(alias = "@locked")]
1532 #[serde(alias = "locked")]
1533 pub locked: bool,
1534
1535 #[serde(rename = "user")]
1536 #[serde(alias = "@user")]
1537 #[serde(alias = "user")]
1538 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1539 pub user: Option<String>,
1540
1541 #[serde(rename = "dateTimeChanged")]
1542 #[serde(alias = "@dateTimeChanged")]
1543 #[serde(alias = "dateTimeChanged")]
1544 #[serde(
1545 default,
1546 deserialize_with = "deserialize_empty_string_as_none_datetime"
1547 )]
1548 pub date_time_changed: Option<DateTime<Utc>>,
1549
1550 #[serde(rename = "formTitle")]
1551 #[serde(alias = "@formTitle")]
1552 #[serde(alias = "formTitle")]
1553 pub form_title: String,
1554 #[serde(rename = "formIndex")]
1555 #[serde(alias = "@formIndex")]
1556 #[serde(alias = "formIndex")]
1557 pub form_index: usize,
1558
1559 #[serde(rename = "formGroup")]
1560 #[serde(alias = "@formGroup")]
1561 #[serde(alias = "formGroup")]
1562 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1563 pub form_group: Option<String>,
1564
1565 #[serde(rename = "formState")]
1566 #[serde(alias = "@formState")]
1567 #[serde(alias = "formState")]
1568 pub form_state: String,
1569
1570 #[serde(alias = "state")]
1571 pub states: Option<Arc<Vec<State>>>,
1572
1573 #[serde(alias = "lockState")]
1574 pub lock_states: Option<Arc<Vec<LockState>>>,
1575
1576 #[serde(alias = "category")]
1577 pub categories: Option<Arc<Vec<Category>>>,
1578}
1579
1580#[cfg(feature = "python")]
1581#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
1582#[pyclass(skip_from_py_object)]
1583pub struct Form {
1584 #[serde(rename = "name")]
1585 #[serde(alias = "@name")]
1586 #[serde(alias = "name")]
1587 pub name: String,
1588
1589 #[serde(rename = "lastModified")]
1590 #[serde(alias = "@lastModified")]
1591 #[serde(alias = "lastModified")]
1592 #[serde(
1593 default,
1594 deserialize_with = "deserialize_empty_string_as_none_datetime"
1595 )]
1596 pub last_modified: Option<DateTime<Utc>>,
1597
1598 #[serde(rename = "whoLastModifiedName")]
1599 #[serde(alias = "@whoLastModifiedName")]
1600 #[serde(alias = "whoLastModifiedName")]
1601 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1602 pub who_last_modified_name: Option<String>,
1603
1604 #[serde(rename = "whoLastModifiedRole")]
1605 #[serde(alias = "@whoLastModifiedRole")]
1606 #[serde(alias = "whoLastModifiedRole")]
1607 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1608 pub who_last_modified_role: Option<String>,
1609
1610 #[serde(rename = "whenCreated")]
1611 #[serde(alias = "@whenCreated")]
1612 #[serde(alias = "whenCreated")]
1613 pub when_created: usize,
1614 #[serde(rename = "hasErrors")]
1615 #[serde(alias = "@hasErrors")]
1616 #[serde(alias = "hasErrors")]
1617 pub has_errors: bool,
1618 #[serde(rename = "hasWarnings")]
1619 #[serde(alias = "@hasWarnings")]
1620 #[serde(alias = "hasWarnings")]
1621 pub has_warnings: bool,
1622 #[serde(rename = "locked")]
1623 #[serde(alias = "@locked")]
1624 #[serde(alias = "locked")]
1625 pub locked: bool,
1626
1627 #[serde(rename = "user")]
1628 #[serde(alias = "@user")]
1629 #[serde(alias = "user")]
1630 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1631 pub user: Option<String>,
1632
1633 #[serde(rename = "dateTimeChanged")]
1634 #[serde(alias = "@dateTimeChanged")]
1635 #[serde(alias = "dateTimeChanged")]
1636 #[serde(
1637 default,
1638 deserialize_with = "deserialize_empty_string_as_none_datetime"
1639 )]
1640 pub date_time_changed: Option<DateTime<Utc>>,
1641
1642 #[serde(rename = "formTitle")]
1643 #[serde(alias = "@formTitle")]
1644 #[serde(alias = "formTitle")]
1645 pub form_title: String,
1646 #[serde(rename = "formIndex")]
1647 #[serde(alias = "@formIndex")]
1648 #[serde(alias = "formIndex")]
1649 pub form_index: usize,
1650
1651 #[serde(rename = "formGroup")]
1652 #[serde(alias = "@formGroup")]
1653 #[serde(alias = "formGroup")]
1654 #[serde(default, deserialize_with = "deserialize_empty_string_as_none")]
1655 pub form_group: Option<String>,
1656
1657 #[serde(rename = "formState")]
1658 #[serde(alias = "@formState")]
1659 #[serde(alias = "formState")]
1660 pub form_state: String,
1661
1662 #[serde(alias = "state")]
1663 pub states: Option<Arc<Vec<State>>>,
1664
1665 #[serde(alias = "lockState")]
1666 pub lock_states: Option<Arc<Vec<LockState>>>,
1667
1668 #[serde(alias = "category")]
1669 pub categories: Option<Arc<Vec<Category>>>,
1670}
1671
1672#[cfg(feature = "python")]
1673#[pymethods]
1674impl Form {
1675 #[getter]
1676 fn name(&self) -> PyResult<String> {
1677 Ok(self.name.clone())
1678 }
1679
1680 #[getter]
1681 fn last_modified<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1682 to_py_datetime_option(py, &self.last_modified)
1683 }
1684
1685 #[getter]
1686 fn who_last_modified_name(&self) -> PyResult<Option<String>> {
1687 Ok(self.who_last_modified_name.clone())
1688 }
1689
1690 #[getter]
1691 fn who_last_modified_role(&self) -> PyResult<Option<String>> {
1692 Ok(self.who_last_modified_role.clone())
1693 }
1694
1695 #[getter]
1696 fn when_created(&self) -> PyResult<usize> {
1697 Ok(self.when_created)
1698 }
1699
1700 #[getter]
1701 fn has_errors(&self) -> PyResult<bool> {
1702 Ok(self.has_errors)
1703 }
1704
1705 #[getter]
1706 fn has_warnings(&self) -> PyResult<bool> {
1707 Ok(self.has_warnings)
1708 }
1709
1710 #[getter]
1711 fn locked(&self) -> PyResult<bool> {
1712 Ok(self.locked)
1713 }
1714
1715 #[getter]
1716 fn user(&self) -> PyResult<Option<String>> {
1717 Ok(self.user.clone())
1718 }
1719
1720 #[getter]
1721 fn date_time_changed<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
1722 to_py_datetime_option(py, &self.date_time_changed)
1723 }
1724
1725 #[getter]
1726 fn form_title(&self) -> PyResult<String> {
1727 Ok(self.form_title.clone())
1728 }
1729
1730 #[getter]
1731 fn form_index(&self) -> PyResult<usize> {
1732 Ok(self.form_index)
1733 }
1734
1735 #[getter]
1736 fn form_group(&self) -> PyResult<Option<String>> {
1737 Ok(self.form_group.clone())
1738 }
1739
1740 #[getter]
1741 fn form_state(&self) -> PyResult<String> {
1742 Ok(self.form_state.clone())
1743 }
1744
1745 #[getter]
1746 fn states(&self) -> PyResult<Option<Vec<State>>> {
1747 Ok(self.states.as_deref().cloned())
1748 }
1749
1750 #[getter]
1751 fn lock_states(&self) -> PyResult<Option<Vec<LockState>>> {
1752 Ok(self.lock_states.as_deref().cloned())
1753 }
1754
1755 #[getter]
1756 fn categories(&self) -> PyResult<Option<Vec<Category>>> {
1757 Ok(self.categories.as_deref().cloned())
1758 }
1759
1760 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
1761 let dict = PyDict::new(py);
1762 dict.set_item("name", &self.name)?;
1763 dict.set_item(
1764 "last_modified",
1765 to_py_datetime_option(py, &self.last_modified)?,
1766 )?;
1767 dict.set_item("who_last_modified_name", &self.who_last_modified_name)?;
1768 dict.set_item("who_last_modified_role", &self.who_last_modified_role)?;
1769 dict.set_item("when_created", self.when_created)?;
1770 dict.set_item("has_errors", self.has_errors)?;
1771 dict.set_item("has_warnings", self.has_warnings)?;
1772 dict.set_item("locked", self.locked)?;
1773 dict.set_item("user", &self.user)?;
1774 dict.set_item(
1775 "date_time_changed",
1776 to_py_datetime_option(py, &self.date_time_changed)?,
1777 )?;
1778 dict.set_item("form_title", &self.form_title)?;
1779 dict.set_item("form_index", self.form_index)?;
1780 dict.set_item("form_group", &self.form_group)?;
1781 dict.set_item("form_state", &self.form_state)?;
1782
1783 let mut state_dicts = Vec::new();
1784 if let Some(states) = &self.states {
1785 for state in states.iter() {
1786 let state_dict = state.to_dict(py)?;
1787 state_dicts.push(state_dict);
1788 }
1789 dict.set_item("states", state_dicts)?;
1790 } else {
1791 dict.set_item("states", py.None())?;
1792 }
1793
1794 let mut lock_state_dicts = Vec::new();
1795 if let Some(lock_states) = &self.lock_states {
1796 for lock_state in lock_states.iter() {
1797 let lock_state_dict = lock_state.to_dict(py)?;
1798 lock_state_dicts.push(lock_state_dict);
1799 }
1800 dict.set_item("lock_states", lock_state_dicts)?;
1801 } else {
1802 dict.set_item("lock_states", py.None())?;
1803 }
1804
1805 if let Some(categories) = &self.categories {
1806 let mut category_dicts = Vec::new();
1807 for category in categories.iter() {
1808 let category_dict = category.to_dict(py)?;
1809 category_dicts.push(category_dict);
1810 }
1811 dict.set_item("categories", category_dicts)?;
1812 } else {
1813 dict.set_item("categories", py.None())?;
1814 }
1815
1816 Ok(dict)
1817 }
1818}
1819
1820impl State {
1821 pub(crate) fn from_attributes(
1822 e: &BytesStart<'_>,
1823 interner: &mut Interner,
1824 ) -> Result<Self, crate::errors::Error> {
1825 let mut value = "";
1826 let mut signer = "";
1827 let mut signer_unique_id = "";
1828 let mut date_signed = "";
1829
1830 visit_attributes(e, |key, attr| match key {
1831 b"value" => value = attr,
1832 b"signer" => signer = attr,
1833 b"signerUniqueId" => signer_unique_id = attr,
1834 b"dateSigned" => date_signed = attr,
1835 _ => {}
1836 })?;
1837
1838 Ok(State {
1839 value: interner.intern(value),
1840 signer: interner.intern(signer),
1841 signer_unique_id: interner.intern(signer_unique_id),
1842 date_signed: optional_datetime(date_signed),
1843 })
1844 }
1845}
1846
1847impl LockState {
1848 pub(crate) fn from_attributes(e: &BytesStart<'_>) -> Result<Self, crate::errors::Error> {
1849 let mut locked = "";
1850 let mut user = "";
1851 let mut user_unique_id = "";
1852 let mut date_time_changed = "";
1853
1854 visit_attributes(e, |key, attr| match key {
1855 b"locked" => locked = attr,
1856 b"user" => user = attr,
1857 b"userUniqueId" => user_unique_id = attr,
1858 b"dateTimeChanged" => date_time_changed = attr,
1859 _ => {}
1860 })?;
1861
1862 Ok(LockState {
1863 locked: locked == "true",
1864 user: optional_string(user),
1865 user_unique_id: optional_string(user_unique_id),
1866 date_time_changed: optional_datetime(date_time_changed),
1867 })
1868 }
1869}
1870
1871impl Category {
1872 pub(crate) fn from_attributes(
1873 e: &BytesStart<'_>,
1874 interner: &mut Interner,
1875 ) -> Result<Self, crate::errors::Error> {
1876 let mut name = "";
1877 let mut category_type = "";
1878 let mut highest_index = "";
1879 let mut obfuscated = "";
1880 let mut over_ride_highest_index = "";
1881
1882 visit_attributes(e, |key, attr| match key {
1883 b"name" => name = attr,
1884 b"type" => category_type = attr,
1885 b"highestIndex" => highest_index = attr,
1886 b"obfuscated" => obfuscated = attr,
1887 b"overRideHighestIndex" => over_ride_highest_index = attr,
1888 _ => {}
1889 })?;
1890
1891 Ok(Category {
1892 name: interner.intern(name),
1893 category_type: interner.intern(category_type),
1894 highest_index: highest_index.parse().unwrap_or(0),
1895 obfuscated: obfuscated == "true",
1896 over_ride_highest_index: over_ride_highest_index == "true",
1897 fields: None,
1898 files: None,
1899 })
1900 }
1901}
1902
1903impl Field {
1904 pub(crate) fn from_attributes(
1905 e: &BytesStart<'_>,
1906 interner: &mut Interner,
1907 ) -> Result<Self, crate::errors::Error> {
1908 let mut name = "";
1909 let mut field_type = "";
1910 let mut data_type = "";
1911 let mut error_code = "";
1912 let mut when_created = "";
1913 let mut keep_history = "";
1914
1915 visit_attributes(e, |key, attr| match key {
1916 b"name" => name = attr,
1917 b"type" => field_type = attr,
1918 b"dataType" => data_type = attr,
1919 b"errorCode" => error_code = attr,
1920 b"whenCreated" => when_created = attr,
1921 b"keepHistory" => keep_history = attr,
1922 _ => {}
1923 })?;
1924
1925 Ok(Field {
1926 name: interner.intern(name),
1927 field_type: interner.intern(field_type),
1928 data_type: interner.intern_optional(data_type),
1929 error_code: interner.intern(error_code),
1930 when_created: checked_datetime(when_created)?,
1931 keep_history: keep_history == "true",
1932 entries: None,
1933 comments: None,
1934 queries: None,
1935 })
1936 }
1937}
1938
1939impl Entry {
1940 pub(crate) fn from_attributes(
1941 e: &BytesStart<'_>,
1942 interner: &mut Interner,
1943 ) -> Result<Self, crate::errors::Error> {
1944 let mut id: Option<&str> = None;
1945 let mut entry_id: Option<&str> = None;
1946 let mut reviewed_by = "";
1947 let mut reviewed_by_unique_id = "";
1948 let mut reviewed_by_when = "";
1949
1950 visit_attributes(e, |key, attr| match key {
1951 b"id" => id = Some(attr),
1952 b"entryId" => entry_id = Some(attr),
1953 b"reviewedBy" => reviewed_by = attr,
1954 b"reviewedByUniqueId" => reviewed_by_unique_id = attr,
1955 b"reviewedByWhen" => reviewed_by_when = attr,
1956 _ => {}
1957 })?;
1958
1959 Ok(Entry {
1960 entry_id: interner.intern(id.or(entry_id).unwrap_or_default()),
1961 reviewed_by: optional_string(reviewed_by),
1962 reviewed_by_unique_id: optional_string(reviewed_by_unique_id),
1963 reviewed_by_when: optional_datetime(reviewed_by_when),
1964 value: None,
1965 reason: None,
1966 })
1967 }
1968}
1969
1970impl Value {
1971 pub(crate) fn from_attributes(
1972 e: &BytesStart<'_>,
1973 interner: &mut Interner,
1974 ) -> Result<Self, crate::errors::Error> {
1975 let mut by = "";
1976 let mut by_unique_id = "";
1977 let mut role = "";
1978 let mut when = "";
1979
1980 visit_attributes(e, |key, attr| match key {
1981 b"by" => by = attr,
1982 b"byUniqueId" => by_unique_id = attr,
1983 b"role" => role = attr,
1984 b"when" => when = attr,
1985 _ => {}
1986 })?;
1987
1988 Ok(Value {
1989 by: interner.intern(by),
1990 by_unique_id: interner.intern_optional(by_unique_id),
1991 role: interner.intern(role),
1992 when: checked_datetime(when)?,
1993 value: String::new(),
1994 })
1995 }
1996}
1997
1998impl Reason {
1999 pub(crate) fn from_attributes(
2000 e: &BytesStart<'_>,
2001 interner: &mut Interner,
2002 ) -> Result<Self, crate::errors::Error> {
2003 let mut by = "";
2004 let mut by_unique_id = "";
2005 let mut role = "";
2006 let mut when = "";
2007
2008 visit_attributes(e, |key, attr| match key {
2009 b"by" => by = attr,
2010 b"byUniqueId" => by_unique_id = attr,
2011 b"role" => role = attr,
2012 b"when" => when = attr,
2013 _ => {}
2014 })?;
2015
2016 Ok(Reason {
2017 by: interner.intern(by),
2018 by_unique_id: interner.intern_optional(by_unique_id),
2019 role: interner.intern(role),
2020 when: checked_datetime(when)?,
2021 value: String::new(),
2022 })
2023 }
2024}
2025
2026impl Export {
2027 pub(crate) fn from_attributes(e: &BytesStart<'_>) -> Result<Self, crate::errors::Error> {
2028 let mut date = "";
2029 let mut created_by = "";
2030 let mut role = "";
2031 let mut number_subjects_processed = "";
2032 let mut page_number = "";
2033
2034 visit_attributes(e, |key, attr| match key {
2035 b"date" => date = attr,
2036 b"createdBy" => created_by = attr,
2037 b"role" => role = attr,
2038 b"numberSubjectsProcessed" => number_subjects_processed = attr,
2039 b"pageNumber" => page_number = attr,
2040 _ => {}
2041 })?;
2042
2043 Ok(Export {
2044 date: optional_datetime(date),
2045 created_by: optional_string(created_by),
2046 role: optional_string(role),
2047 number_subjects_processed: number_subjects_processed.parse().ok(),
2048 page_number: optional_string(page_number),
2049 })
2050 }
2051}
2052
2053#[cfg(feature = "python")]
2054#[pymethods]
2055impl Export {
2056 #[getter]
2057 fn date<'py>(&self, py: Python<'py>) -> PyResult<Option<Bound<'py, PyDateTime>>> {
2058 to_py_datetime_option(py, &self.date)
2059 }
2060
2061 #[getter]
2062 fn created_by(&self) -> PyResult<Option<String>> {
2063 Ok(self.created_by.clone())
2064 }
2065
2066 #[getter]
2067 fn role(&self) -> PyResult<Option<String>> {
2068 Ok(self.role.clone())
2069 }
2070
2071 #[getter]
2072 fn number_subjects_processed(&self) -> PyResult<Option<usize>> {
2073 Ok(self.number_subjects_processed)
2074 }
2075
2076 #[getter]
2077 fn page_number(&self) -> PyResult<Option<String>> {
2078 Ok(self.page_number.clone())
2079 }
2080
2081 pub fn to_dict<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyDict>> {
2082 let dict = PyDict::new(py);
2083 dict.set_item("date", to_py_datetime_option(py, &self.date)?)?;
2084 dict.set_item("created_by", &self.created_by)?;
2085 dict.set_item("role", &self.role)?;
2086 dict.set_item("number_subjects_processed", self.number_subjects_processed)?;
2087 dict.set_item("page_number", &self.page_number)?;
2088
2089 Ok(dict)
2090 }
2091}
2092
2093impl Query {
2094 pub(crate) fn from_attributes(
2095 e: &BytesStart<'_>,
2096 interner: &mut Interner,
2097 ) -> Result<Self, crate::errors::Error> {
2098 let mut id: Option<&str> = None;
2099 let mut query_id: Option<&str> = None;
2100 let mut reviewed_by = "";
2101 let mut reviewed_by_unique_id = "";
2102 let mut reviewed_by_when = "";
2103
2104 visit_attributes(e, |key, attr| match key {
2105 b"id" => id = Some(attr),
2106 b"queryId" => query_id = Some(attr),
2107 b"reviewedBy" => reviewed_by = attr,
2108 b"reviewedByUniqueId" => reviewed_by_unique_id = attr,
2109 b"reviewedByWhen" => reviewed_by_when = attr,
2110 _ => {}
2111 })?;
2112
2113 Ok(Query {
2114 query_id: interner.intern(id.or(query_id).unwrap_or_default()),
2115 reviewed_by: optional_string(reviewed_by),
2116 reviewed_by_unique_id: optional_string(reviewed_by_unique_id),
2117 reviewed_by_when: optional_datetime(reviewed_by_when),
2118 value: None,
2119 answer: None,
2120 })
2121 }
2122}
2123
2124impl File {
2125 pub(crate) fn from_attributes(
2126 e: &BytesStart<'_>,
2127 interner: &mut Interner,
2128 ) -> Result<Self, crate::errors::Error> {
2129 let mut name = "";
2130 let mut file_type = "";
2131 let mut data_type = "";
2132 let mut error_code = "";
2133 let mut when_created = "";
2134 let mut keep_history = "";
2135 let mut file_location = "";
2136 let mut size = "";
2137
2138 visit_attributes(e, |key, attr| match key {
2139 b"name" => name = attr,
2140 b"type" => file_type = attr,
2141 b"dataType" => data_type = attr,
2142 b"errorCode" => error_code = attr,
2143 b"whenCreated" => when_created = attr,
2144 b"keepHistory" => keep_history = attr,
2145 b"fileLocation" => file_location = attr,
2146 b"size" => size = attr,
2147 _ => {}
2148 })?;
2149
2150 Ok(File {
2151 name: interner.intern(name),
2152 file_type: interner.intern(file_type),
2153 data_type: interner.intern_optional(data_type),
2154 error_code: interner.intern(error_code),
2155 when_created: checked_datetime(when_created)?,
2156 keep_history: keep_history == "true",
2157 file_location: optional_string(file_location),
2158 size: size.parse().ok(),
2159 entries: None,
2160 comments: None,
2161 queries: None,
2162 download_history: None,
2163 })
2164 }
2165}
2166
2167impl Comment {
2168 pub(crate) fn from_attributes(e: &BytesStart<'_>) -> Result<Self, crate::errors::Error> {
2169 let mut comment_id = "";
2170 let mut reviewed_by = "";
2171 let mut reviewed_by_unique_id = "";
2172 let mut reviewed_by_when = "";
2173
2174 visit_attributes(e, |key, attr| match key {
2175 b"id" => comment_id = attr,
2176 b"reviewedBy" => reviewed_by = attr,
2177 b"reviewedByUniqueId" => reviewed_by_unique_id = attr,
2178 b"reviewedByWhen" => reviewed_by_when = attr,
2179 _ => {}
2180 })?;
2181
2182 Ok(Comment {
2183 comment_id: attribute_string(comment_id),
2184 reviewed_by: optional_string(reviewed_by),
2185 reviewed_by_unique_id: optional_string(reviewed_by_unique_id),
2186 reviewed_by_when: optional_datetime(reviewed_by_when),
2187 value: None,
2188 })
2189 }
2190}