use std::io::Write;
use std::sync::Arc;
use quick_xml::events::{BytesEnd, BytesStart, Event};
use quick_xml::Result;
use crate::obo::{Ontology, MZML_ONTOLOGY};
use super::cvparam::{Accession, CVParam, CVParamValue};
use super::MzMLTag;
pub struct Writer<W: Write> {
writer: quick_xml::Writer<W>,
ontology: Ontology,
}
impl<W: Write> Writer<W> {
pub fn new(inner: W) -> Result<Self> {
Self::with_ontology(inner, MZML_ONTOLOGY.clone())
}
pub fn with_ontology(inner: W, ontology: Ontology) -> Result<Self> {
let mut writer = quick_xml::Writer::new_with_indent(inner, b' ', 2);
let decl_elem = quick_xml::events::BytesDecl::new("1.1", Some("UTF-8"), Some("yes"));
writer.write_event(quick_xml::events::Event::Decl(decl_elem))?;
Ok(Self { writer, ontology })
}
pub fn ontology(&self) -> &Ontology {
&self.ontology
}
pub fn start_tag(&mut self, tag_name: &str) -> Result<()> {
let elem = BytesStart::new(tag_name);
self.writer.write_event(Event::Start(elem))
}
pub fn end_tag(&mut self, name: &str) -> Result<()> {
self.writer.write_event(Event::End(BytesEnd::new(name)))
}
pub fn empty_tag(&mut self, tag_name: &str) -> Result<()> {
let empty_tag = BytesStart::new(tag_name);
self.writer.write_event(Event::Empty(empty_tag))
}
pub fn start_tag_with_attr<D: std::fmt::Display>(
&mut self,
tag_name: &str,
attribute_name: &str,
value: D,
) -> Result<()> {
let mut elem = BytesStart::new(tag_name);
elem.push_attribute((attribute_name, format!("{}", value).as_str()));
self.writer.write_event(Event::Start(elem))
}
pub fn empty_tag_with_attr<D: std::fmt::Display>(
&mut self,
tag_name: &str,
attribute_name: &str,
value: D,
) -> Result<()> {
let mut empty_tag = BytesStart::new(tag_name);
empty_tag.push_attribute((attribute_name, format!("{}", value).as_str()));
self.writer.write_event(Event::Empty(empty_tag))
}
pub fn write_event<'a, E: AsRef<Event<'a>>>(&mut self, event: E) -> Result<()> {
self.writer.write_event(event)
}
pub fn write_list<T: MzMLTag>(&mut self, tag_name: &str, list: &[T]) -> Result<()> {
self.start_tag_with_attr(tag_name, "count", list.len())?;
for item in list {
item.write_xml(self)?;
}
self.end_tag(tag_name)
}
pub fn write_arc_list<T: MzMLTag>(&mut self, tag_name: &str, list: &[Arc<T>]) -> Result<()> {
self.start_tag_with_attr(tag_name, "count", list.len())?;
for item in list {
item.write_xml(self)?;
}
self.end_tag(tag_name)
}
pub fn write_param(&mut self, accession: &str, value: CVParamValue) -> Result<()> {
let param = CVParam::new(
Accession::Term(self.ontology.get(accession).unwrap().clone()),
value,
);
param.write_xml(self)
}
}