use crate::models::{meta::MetaTypeVariant, schema::MaxOccurs, TypeIdent};
use super::{Error, Optimizer};
impl Optimizer {
#[doc = include_str!("../../../tests/optimizer/complex_choice.xsd")]
#[doc = include_str!("../../../tests/optimizer/expected0/merge_choice_cardinalities.rs")]
#[doc = include_str!("../../../tests/optimizer/expected1/merge_choice_cardinalities.rs")]
pub fn merge_choice_cardinality(mut self, ident: TypeIdent) -> Result<Self, Error> {
tracing::debug!("merge_choice_cardinality(ident={ident:?})");
let Some(ty) = self.types.get_variant(&ident) else {
return Err(Error::UnknownType(ident));
};
let MetaTypeVariant::ComplexType(ci) = ty else {
return Err(Error::ExpectedComplexType(ident));
};
let Some(content_ident) = ci.content.clone() else {
return Err(Error::MissingContentType(ident));
};
let Some(MetaTypeVariant::Choice(ci)) = self.types.get_variant_mut(&content_ident) else {
return Err(Error::ExpectedComplexChoice(ident));
};
let mut min = 1;
let mut max = MaxOccurs::Bounded(1);
for element in &mut *ci.elements {
min = min.min(element.min_occurs);
max = max.max(element.max_occurs);
element.min_occurs = 1;
element.max_occurs = MaxOccurs::Bounded(1);
}
let Some(MetaTypeVariant::ComplexType(ci)) = self.types.get_variant_mut(&ident) else {
unreachable!();
};
ci.min_occurs = min.min(ci.min_occurs);
ci.max_occurs = max.max(ci.max_occurs);
Ok(self)
}
pub fn merge_choice_cardinalities(mut self) -> Self {
tracing::debug!("merge_choice_cardinalities");
let idents = self
.types
.items
.iter()
.filter_map(|(ident, type_)| {
if matches!(&type_.variant, MetaTypeVariant::ComplexType(ci) if ci.has_complex_choice_content(&self.types)) {
Some(ident)
} else {
None
}
})
.cloned()
.collect::<Vec<_>>();
for ident in idents {
self = self.merge_choice_cardinality(ident).unwrap();
}
self
}
}