use super::types::{EntityType, ReferenceStyle};
use indexmap::IndexMap;
#[derive(Debug, Clone)]
pub struct ReferenceGenerator {
style: ReferenceStyle,
counters: IndexMap<EntityType, u32>,
prefixes: IndexMap<EntityType, String>,
}
impl ReferenceGenerator {
pub fn new(style: ReferenceStyle) -> Self {
let mut prefixes = IndexMap::new();
prefixes.insert(EntityType::Release, "R".to_string());
prefixes.insert(EntityType::Resource, "A".to_string());
prefixes.insert(EntityType::Party, "P".to_string());
prefixes.insert(EntityType::Deal, "D".to_string());
prefixes.insert(EntityType::TechnicalDetails, "T".to_string());
prefixes.insert(EntityType::RightsController, "RC".to_string());
Self {
style,
counters: IndexMap::new(),
prefixes,
}
}
pub fn generate(&mut self, entity_type: EntityType) -> String {
match self.style.clone() {
ReferenceStyle::Sequential => self.generate_sequential(entity_type),
ReferenceStyle::Custom(formatter) => {
formatter(entity_type, self.next_counter(entity_type))
}
ReferenceStyle::Prefixed { separator } => {
self.generate_prefixed(entity_type, &separator)
}
}
}
fn generate_sequential(&mut self, entity_type: EntityType) -> String {
let prefix = self
.prefixes
.get(&entity_type)
.expect("Unknown entity type")
.clone(); let counter = self.next_counter(entity_type);
format!("{}{}", prefix, counter)
}
fn generate_prefixed(&mut self, entity_type: EntityType, separator: &str) -> String {
let prefix = self
.prefixes
.get(&entity_type)
.expect("Unknown entity type")
.clone(); let counter = self.next_counter(entity_type);
format!("{}{}{}", prefix, separator, counter)
}
fn next_counter(&mut self, entity_type: EntityType) -> u32 {
let counter = self.counters.entry(entity_type).or_insert(0);
*counter += 1;
*counter
}
pub fn set_prefix(&mut self, entity_type: EntityType, prefix: String) {
self.prefixes.insert(entity_type, prefix);
}
pub fn reset_counter(&mut self, entity_type: EntityType) {
self.counters.insert(entity_type, 0);
}
pub fn reset_all_counters(&mut self) {
self.counters.clear();
}
pub fn get_counter(&self, entity_type: EntityType) -> u32 {
self.counters.get(&entity_type).copied().unwrap_or(0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sequential_generation() {
let mut gen = ReferenceGenerator::new(ReferenceStyle::Sequential);
assert_eq!(gen.generate(EntityType::Resource), "A1");
assert_eq!(gen.generate(EntityType::Resource), "A2");
assert_eq!(gen.generate(EntityType::Release), "R1");
assert_eq!(gen.generate(EntityType::Resource), "A3");
assert_eq!(gen.generate(EntityType::Release), "R2");
}
#[test]
fn test_deterministic_ordering() {
let mut gen1 = ReferenceGenerator::new(ReferenceStyle::Sequential);
let mut gen2 = ReferenceGenerator::new(ReferenceStyle::Sequential);
for _ in 0..5 {
assert_eq!(
gen1.generate(EntityType::Resource),
gen2.generate(EntityType::Resource)
);
}
}
}