use crate::models::meta::{DynamicMeta, GroupMeta, MetaTypeVariant};
use crate::models::schema::{NamespaceId, NamespaceInfo, Schemas};
use super::State;
impl State<'_> {
pub(super) fn fix_element_naming_conflicts(&mut self) {
for type_ in self.types.items.values_mut() {
match &mut type_.variant {
MetaTypeVariant::All(x)
| MetaTypeVariant::Choice(x)
| MetaTypeVariant::Sequence(x) => {
fix_naming_conflicts(self.schemas, x);
}
MetaTypeVariant::Dynamic(x) => fix_naming_conflicts(self.schemas, x),
_ => {}
}
}
}
}
fn fix_naming_conflicts<X>(schemas: &Schemas, meta: &mut X)
where
X: IdentSlice,
{
let len = meta.len();
for i in 0..len {
let mut index = 2;
let mut ns_renamed = false;
for j in i + 1..len {
let ident_i = &meta.get_ident(i);
let ident_j = &meta.get_ident(j);
if ident_i.1 == ident_j.1 {
if ident_i.0 == ident_j.0 {
let display_name = make_index_display_name(ident_j.1, &mut index);
meta.set_display_name(j, Some(display_name));
} else {
ns_renamed = true;
let display_name = make_ns_display_name(ident_j.0, ident_j.1, schemas);
meta.set_display_name(j, display_name);
}
}
}
if ns_renamed {
let ident = meta.get_ident(i);
let display_name = make_ns_display_name(ident.0, ident.1, schemas);
meta.set_display_name(i, display_name);
}
}
}
fn make_ns_display_name(ns: NamespaceId, name: &str, schemas: &Schemas) -> Option<String> {
let prefix = schemas
.get_namespace_info(&ns)
.and_then(NamespaceInfo::name);
prefix.map(|prefix| format!("{prefix}_{name}"))
}
fn make_index_display_name(name: &str, index: &mut usize) -> String {
let name = format!("{name}_{index}");
*index += 1;
name
}
trait IdentSlice {
fn len(&self) -> usize;
fn get_ident(&self, index: usize) -> (NamespaceId, &str);
fn set_display_name(&mut self, index: usize, display_name: Option<String>);
}
impl IdentSlice for GroupMeta {
fn len(&self) -> usize {
self.elements.len()
}
fn get_ident(&self, index: usize) -> (NamespaceId, &str) {
let el = &self.elements[index];
(el.ident.ns, el.ident.name.as_str())
}
fn set_display_name(&mut self, index: usize, display_name: Option<String>) {
self.elements[index].display_name = display_name;
}
}
impl IdentSlice for DynamicMeta {
fn len(&self) -> usize {
self.derived_types.len()
}
fn get_ident(&self, index: usize) -> (NamespaceId, &str) {
let type_ = &self.derived_types[index].type_;
(type_.ns, type_.name.as_str())
}
fn set_display_name(&mut self, index: usize, display_name: Option<String>) {
self.derived_types[index].display_name = display_name;
}
}