use super::condition::TransitionCondition;
use super::converter::OrgConverter;
use crate::plugin::org_suite::types::{OrgArchetype, OrgSuiteError};
use std::collections::HashMap;
pub struct TransitionRegistry {
converters: HashMap<(OrgArchetype, OrgArchetype), Box<dyn OrgConverter>>,
conditions: Vec<Box<dyn TransitionCondition>>,
}
impl TransitionRegistry {
pub fn new() -> Self {
Self {
converters: HashMap::new(),
conditions: Vec::new(),
}
}
pub fn register_converter(&mut self, converter: Box<dyn OrgConverter>) {
let key = (converter.source_archetype(), converter.target_archetype());
self.converters.insert(key, converter);
}
pub fn register_condition(&mut self, condition: Box<dyn TransitionCondition>) {
self.conditions.push(condition);
}
pub fn get_converter(
&self,
from: OrgArchetype,
to: OrgArchetype,
) -> Result<&dyn OrgConverter, OrgSuiteError> {
self.converters
.get(&(from, to))
.map(|b| b.as_ref())
.ok_or(OrgSuiteError::ConverterNotFound { from, to })
}
pub fn is_transition_valid(&self, from: OrgArchetype, to: OrgArchetype) -> bool {
self.converters.contains_key(&(from, to))
}
pub fn conditions(&self) -> &[Box<dyn TransitionCondition>] {
&self.conditions
}
pub fn converter_count(&self) -> usize {
self.converters.len()
}
pub fn condition_count(&self) -> usize {
self.conditions.len()
}
}
impl Default for TransitionRegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::super::condition::ConditionContext;
use super::*;
use crate::plugin::org_suite::types::TransitionTrigger;
struct MockConverter {
from: OrgArchetype,
to: OrgArchetype,
}
impl OrgConverter for MockConverter {
fn source_archetype(&self) -> OrgArchetype {
self.from
}
fn target_archetype(&self) -> OrgArchetype {
self.to
}
fn convert(
&self,
_source_data: &serde_json::Value,
) -> Result<serde_json::Value, OrgSuiteError> {
Ok(serde_json::json!({"converted": true}))
}
}
struct MockCondition;
impl TransitionCondition for MockCondition {
fn evaluate(
&self,
_faction_id: &str,
_current: OrgArchetype,
_context: &ConditionContext,
) -> Option<TransitionTrigger> {
None
}
}
#[test]
fn test_register_and_get_converter() {
let mut registry = TransitionRegistry::new();
let converter = Box::new(MockConverter {
from: OrgArchetype::Holacracy,
to: OrgArchetype::Hierarchy,
});
registry.register_converter(converter);
assert!(registry.is_transition_valid(OrgArchetype::Holacracy, OrgArchetype::Hierarchy));
let result = registry.get_converter(OrgArchetype::Holacracy, OrgArchetype::Hierarchy);
assert!(result.is_ok());
}
#[test]
fn test_get_converter_not_found() {
let registry = TransitionRegistry::new();
let result = registry.get_converter(OrgArchetype::Culture, OrgArchetype::Social);
assert!(result.is_err());
match result {
Err(OrgSuiteError::ConverterNotFound { from, to }) => {
assert_eq!(from, OrgArchetype::Culture);
assert_eq!(to, OrgArchetype::Social);
}
_ => panic!("Expected ConverterNotFound error"),
}
}
#[test]
fn test_register_condition() {
let mut registry = TransitionRegistry::new();
registry.register_condition(Box::new(MockCondition));
assert_eq!(registry.condition_count(), 1);
assert_eq!(registry.conditions().len(), 1);
}
#[test]
fn test_multiple_converters() {
let mut registry = TransitionRegistry::new();
registry.register_converter(Box::new(MockConverter {
from: OrgArchetype::Holacracy,
to: OrgArchetype::Hierarchy,
}));
registry.register_converter(Box::new(MockConverter {
from: OrgArchetype::Hierarchy,
to: OrgArchetype::Social,
}));
assert_eq!(registry.converter_count(), 2);
assert!(registry.is_transition_valid(OrgArchetype::Holacracy, OrgArchetype::Hierarchy));
assert!(registry.is_transition_valid(OrgArchetype::Hierarchy, OrgArchetype::Social));
assert!(!registry.is_transition_valid(OrgArchetype::Social, OrgArchetype::Culture));
}
#[test]
fn test_default() {
let registry = TransitionRegistry::default();
assert_eq!(registry.converter_count(), 0);
assert_eq!(registry.condition_count(), 0);
}
}