use crate::config::ProjectConfig;
use crate::detectors::DetectorTrait;
use crate::models::Service;
use anyhow::Result;
use std::collections::HashMap;
use std::path::Path;
use tracing::debug;
pub struct DetectorRegistry {
detectors: HashMap<String, Box<dyn DetectorTrait>>,
enabled: Vec<String>,
}
impl DetectorRegistry {
pub fn new() -> Self {
Self {
detectors: HashMap::new(),
enabled: Vec::new(),
}
}
pub fn register(&mut self, id: String, detector: Box<dyn DetectorTrait>) {
debug!("Registering detector: {}", id);
self.detectors.insert(id.clone(), detector);
}
pub fn enable(&mut self, ids: Vec<String>) {
self.enabled = ids;
}
pub fn get_enabled(&self) -> Vec<&dyn DetectorTrait> {
let mut enabled_detectors: Vec<(&String, &dyn DetectorTrait)> = self
.detectors
.iter()
.filter(|(id, _)| self.enabled.contains(id))
.map(|(id, detector)| (id, detector.as_ref()))
.collect();
enabled_detectors.sort_by(|a, b| b.1.priority().cmp(&a.1.priority()));
enabled_detectors.into_iter().map(|(_, detector)| detector).collect()
}
pub async fn detect(
&self,
project_path: &Path,
config: Option<&ProjectConfig>,
) -> Result<Vec<Service>> {
let mut all_services = Vec::new();
for detector in self.get_enabled() {
debug!("Running detector: {}", detector.name());
let services = detector.detect(project_path, config).await?;
debug!("Detector {} found {} services", detector.name(), services.len());
all_services.extend(services);
}
Ok(all_services)
}
pub fn is_registered(&self, id: &str) -> bool {
self.detectors.contains_key(id)
}
pub fn registered_ids(&self) -> Vec<String> {
self.detectors.keys().cloned().collect()
}
}
impl Default for DetectorRegistry {
fn default() -> Self {
Self::new()
}
}