#![allow(dead_code)]
use crate::component_catalog::{Component, ComponentCatalog, ComponentType};
use anyhow::Result;
pub struct ComponentCatalogService {
catalog: ComponentCatalog,
}
impl ComponentCatalogService {
pub fn new() -> Self {
Self {
catalog: ComponentCatalog::new(),
}
}
pub fn get_all(&self) -> Vec<&Component> {
self.catalog.get_all()
}
pub fn get_drivers(&self) -> Vec<&Component> {
self.catalog.get_by_type(ComponentType::Driver)
}
pub fn get_packages(&self) -> Vec<&Component> {
self.catalog.get_by_type(ComponentType::Package)
}
pub fn get_behaviors(&self) -> Vec<&Component> {
self.catalog.get_by_type(ComponentType::Behavior)
}
pub fn get_stacks(&self) -> Vec<&Component> {
self.catalog.get_by_type(ComponentType::Stack)
}
pub fn get_by_type(&self, component_type: ComponentType) -> Vec<&Component> {
self.catalog.get_by_type(component_type)
}
pub fn get(&self, id: &str) -> Option<&Component> {
self.catalog.get(id)
}
pub fn search(&self, query: &str) -> Vec<&Component> {
self.catalog.search(query)
}
pub fn get_by_category(&self, category: &str) -> Vec<&Component> {
self.catalog
.get_all()
.into_iter()
.filter(|c| c.category == category)
.collect()
}
pub fn list_categories(&self) -> Vec<String> {
let mut categories: Vec<String> = self.catalog.get_all().iter().map(|c| c.category.clone()).collect();
categories.sort();
categories.dedup();
categories
}
pub fn list_tags(&self) -> Vec<String> {
let mut tags: Vec<String> = self
.catalog
.get_all()
.iter()
.flat_map(|c| c.tags.iter().cloned())
.collect();
tags.sort();
tags.dedup();
tags
}
pub fn get_by_tag(&self, tag: &str) -> Vec<&Component> {
self.catalog
.get_all()
.into_iter()
.filter(|c| c.tags.iter().any(|t| t == tag))
.collect()
}
pub fn get_counts(&self) -> (usize, usize, usize, usize) {
let drivers = self.get_drivers().len();
let packages = self.get_packages().len();
let behaviors = self.get_behaviors().len();
let stacks = self.get_stacks().len();
(drivers, packages, behaviors, stacks)
}
pub fn exists(&self, id: &str) -> bool {
self.catalog.get(id).is_some()
}
pub fn get_recommended_for_platform(&self, platform: &str) -> Vec<&Component> {
match platform.to_lowercase().as_str() {
"rover" => self
.search("lidar")
.into_iter()
.chain(self.search("camera"))
.chain(self.search("imu"))
.collect(),
"arm" => self
.search("joint")
.into_iter()
.chain(self.search("gripper"))
.chain(self.search("camera"))
.collect(),
_ => vec![],
}
}
pub fn validate_dependencies(&self, component_id: &str) -> Result<Vec<String>> {
let component = self
.get(component_id)
.ok_or_else(|| anyhow::anyhow!("Component not found: {}", component_id))?;
let deps: Vec<String> = component
.cargo_dependencies
.iter()
.map(|dep| {
if let Some(version) = &dep.version {
format!("{} = \"{}\"", dep.name, version)
} else if let Some(path) = &dep.path {
format!("{} (path: {})", dep.name, path)
} else {
dep.name.clone()
}
})
.collect();
Ok(deps)
}
}
impl Default for ComponentCatalogService {
fn default() -> Self {
Self::new()
}
}