use std::sync::Arc;
use anyhow::Result;
use async_trait::async_trait;
#[derive(Debug, thiserror::Error)]
pub enum IntegrationError {
#[error("External service unavailable: {0}")]
ServiceUnavailable(String),
#[error("Translation failed: {0}")]
TranslationFailed(String),
#[error("External entity not found: {0}")]
NotFound(String),
#[error("Integration error: {0}")]
Other(#[from] anyhow::Error),
}
#[async_trait]
pub trait ModuleAdapter: Send + Sync {
type External;
type Internal;
fn to_internal(&self, external: Self::External) -> Result<Self::Internal, IntegrationError>;
fn to_external(&self, internal: Self::Internal) -> Result<Self::External, IntegrationError>;
}
#[async_trait]
pub trait ModuleFacade: Send + Sync {
async fn is_available(&self) -> bool;
fn module_name(&self) -> &'static str;
}
pub struct IntegrationRegistry {
adapters: std::collections::HashMap<String, Arc<dyn std::any::Any + Send + Sync>>,
}
impl IntegrationRegistry {
pub fn new() -> Self {
Self {
adapters: std::collections::HashMap::new(),
}
}
pub fn register<T: Send + Sync + 'static>(&mut self, module_name: &str, adapter: Arc<T>) {
self.adapters.insert(module_name.to_string(), adapter);
}
pub fn get<T: Send + Sync + 'static>(&self, module_name: &str) -> Option<Arc<T>> {
self.adapters
.get(module_name)
.and_then(|a| Arc::clone(a).downcast::<T>().ok())
}
pub fn has(&self, module_name: &str) -> bool {
self.adapters.contains_key(module_name)
}
}
impl Default for IntegrationRegistry {
fn default() -> Self {
Self::new()
}
}