mod base_types;
use crate::base_types::Constraint;
pub use base_types::{
Compartment, InitialAssignment, Model, ModelUnits, Parameter, Specie, Unit, UnitSId, UnitSidRef,
};
use std::collections::HashMap;
#[cfg(test)]
mod tests;
pub fn parse_document(doc: &str) -> Result<Model, roxmltree::Error> {
let res = roxmltree::Document::parse(doc)?;
let raw_model = res
.descendants()
.find(|n| n.tag_name().name() == "model")
.unwrap();
let model_units: ModelUnits = ModelUnits::from(raw_model.attributes());
let unit_definitions: HashMap<String, HashMap<UnitSId, Unit>> = raw_model
.descendants()
.filter(|n| n.tag_name().name() == "unitDefinition")
.map(|r| {
(
r.attribute("id").unwrap().to_owned(),
r.descendants()
.filter(|n| n.tag_name().name() == "unit")
.map(|r| {
(
r.attribute("kind")
.map(serde_plain::from_str)
.unwrap()
.unwrap(),
Unit::from(r),
)
})
.collect(),
)
})
.collect();
let compartments: HashMap<String, Compartment> = raw_model
.descendants()
.filter(|n| n.tag_name().name() == "compartment")
.map(|n| (n.attribute("id").unwrap().to_owned(), Compartment::from(n)))
.collect();
let species: HashMap<String, Specie> = raw_model
.descendants()
.filter(|n| n.tag_name().name() == "species")
.map(|n| (n.attribute("id").unwrap().to_owned(), Specie::from(n)))
.collect();
let parameters: HashMap<String, Parameter> = raw_model
.descendants()
.filter(|n| n.tag_name().name() == "parameter")
.map(|n| (n.attribute("id").unwrap().to_owned(), Parameter::from(n)))
.collect();
let initial_assignments: HashMap<String, InitialAssignment> = raw_model
.descendants()
.filter(|n| n.tag_name().name() == "initialAssignment")
.map(|n| {
(
n.attribute("id").unwrap().to_owned(),
InitialAssignment {
symbol: n.attribute("symbol").unwrap().to_owned(),
},
)
})
.collect();
let constraints: Vec<Constraint> = raw_model
.descendants()
.filter(|n| n.tag_name().name() == "constraint")
.map(|n| Constraint {
math: n
.descendants()
.filter(|n| n.tag_name().name() == "math")
.nth(0)
.map(mathml::parse_node),
message: n
.descendants()
.filter(|n| n.tag_name().name() == "message")
.nth(0)
.unwrap()
.children()
.map(|n| n.text().unwrap().trim().to_owned())
.collect::<String>(),
})
.collect();
Ok(Model {
model_units,
parameters,
initial_assignments,
species,
compartments,
unit_definitions,
constraints,
})
}