Skip to main content

pdf_ast/plugins/
registry.rs

1use super::*;
2use crate::ast::NodeType;
3use std::collections::HashMap;
4use std::sync::{Arc, RwLock};
5
6/// Plugin registry for managing registered plugins
7pub struct PluginRegistry {
8    plugins: Arc<RwLock<HashMap<String, Arc<dyn AstPlugin>>>>,
9    plugin_metadata: Arc<RwLock<HashMap<String, PluginMetadata>>>,
10    type_mappings: Arc<RwLock<HashMap<NodeType, Vec<String>>>>,
11}
12
13impl PluginRegistry {
14    pub fn new() -> Self {
15        Self {
16            plugins: Arc::new(RwLock::new(HashMap::new())),
17            plugin_metadata: Arc::new(RwLock::new(HashMap::new())),
18            type_mappings: Arc::new(RwLock::new(HashMap::new())),
19        }
20    }
21
22    /// Register a plugin
23    pub fn register(&self, plugin: Arc<dyn AstPlugin>) -> PluginResult {
24        let metadata = plugin.metadata().clone();
25        let name = metadata.name.clone();
26
27        // Check for duplicate names
28        {
29            let plugins = self.plugins.read().unwrap();
30            if plugins.contains_key(&name) {
31                return PluginResult::Error(format!("Plugin '{}' already registered", name));
32            }
33        }
34
35        // Register plugin
36        {
37            let mut plugins = self.plugins.write().unwrap();
38            plugins.insert(name.clone(), plugin.clone());
39        }
40
41        // Store metadata
42        {
43            let mut plugin_metadata = self.plugin_metadata.write().unwrap();
44            plugin_metadata.insert(name.clone(), metadata.clone());
45        }
46
47        // Update type mappings
48        {
49            let mut type_mappings = self.type_mappings.write().unwrap();
50            for node_type_str in &metadata.supported_node_types {
51                if let Ok(node_type) = self.parse_node_type(node_type_str) {
52                    type_mappings
53                        .entry(node_type)
54                        .or_default()
55                        .push(name.clone());
56                }
57            }
58        }
59
60        PluginResult::Success
61    }
62
63    /// Unregister a plugin
64    pub fn unregister(&self, name: &str) -> PluginResult {
65        // Remove from main registry
66        let plugin_existed = {
67            let mut plugins = self.plugins.write().unwrap();
68            plugins.remove(name).is_some()
69        };
70
71        if !plugin_existed {
72            return PluginResult::Error(format!("Plugin '{}' not found", name));
73        }
74
75        // Remove metadata
76        let metadata = {
77            let mut plugin_metadata = self.plugin_metadata.write().unwrap();
78            plugin_metadata.remove(name)
79        };
80
81        // Update type mappings
82        if let Some(metadata) = metadata {
83            let mut type_mappings = self.type_mappings.write().unwrap();
84            for node_type_str in &metadata.supported_node_types {
85                if let Ok(node_type) = self.parse_node_type(node_type_str) {
86                    if let Some(plugin_names) = type_mappings.get_mut(&node_type) {
87                        plugin_names.retain(|n| n != name);
88                        if plugin_names.is_empty() {
89                            type_mappings.remove(&node_type);
90                        }
91                    }
92                }
93            }
94        }
95
96        PluginResult::Success
97    }
98
99    /// Get a plugin by name
100    pub fn get_plugin(&self, name: &str) -> Option<Arc<dyn AstPlugin>> {
101        let plugins = self.plugins.read().unwrap();
102        plugins.get(name).cloned()
103    }
104
105    /// Get all registered plugin names
106    pub fn list_plugins(&self) -> Vec<String> {
107        let plugins = self.plugins.read().unwrap();
108        plugins.keys().cloned().collect()
109    }
110
111    /// Get plugins that can process a specific node type
112    pub fn get_plugins_for_type(&self, node_type: &NodeType) -> Vec<Arc<dyn AstPlugin>> {
113        let type_mappings = self.type_mappings.read().unwrap();
114        let plugins = self.plugins.read().unwrap();
115
116        if let Some(plugin_names) = type_mappings.get(node_type) {
117            plugin_names
118                .iter()
119                .filter_map(|name| plugins.get(name).cloned())
120                .collect()
121        } else {
122            Vec::new()
123        }
124    }
125
126    /// Get plugin metadata
127    pub fn get_metadata(&self, name: &str) -> Option<PluginMetadata> {
128        let plugin_metadata = self.plugin_metadata.read().unwrap();
129        plugin_metadata.get(name).cloned()
130    }
131
132    /// Get all plugin metadata
133    pub fn list_metadata(&self) -> Vec<PluginMetadata> {
134        let plugin_metadata = self.plugin_metadata.read().unwrap();
135        plugin_metadata.values().cloned().collect()
136    }
137
138    /// Find plugins by tag
139    pub fn find_by_tag(&self, tag: &str) -> Vec<String> {
140        let plugin_metadata = self.plugin_metadata.read().unwrap();
141        plugin_metadata
142            .iter()
143            .filter(|(_, metadata)| metadata.tags.contains(&tag.to_string()))
144            .map(|(name, _)| name.clone())
145            .collect()
146    }
147
148    /// Find plugins by author
149    pub fn find_by_author(&self, author: &str) -> Vec<String> {
150        let plugin_metadata = self.plugin_metadata.read().unwrap();
151        plugin_metadata
152            .iter()
153            .filter(|(_, metadata)| metadata.author == author)
154            .map(|(name, _)| name.clone())
155            .collect()
156    }
157
158    /// Check plugin dependencies
159    pub fn check_dependencies(&self, name: &str) -> PluginResult {
160        let plugin_metadata = self.plugin_metadata.read().unwrap();
161
162        if let Some(metadata) = plugin_metadata.get(name) {
163            for dependency in &metadata.dependencies {
164                if !plugin_metadata.contains_key(dependency) {
165                    return PluginResult::Error(format!(
166                        "Plugin '{}' depends on '{}' which is not registered",
167                        name, dependency
168                    ));
169                }
170            }
171            PluginResult::Success
172        } else {
173            PluginResult::Error(format!("Plugin '{}' not found", name))
174        }
175    }
176
177    /// Get dependency graph for a plugin
178    pub fn get_dependency_order(&self, plugin_names: &[String]) -> Result<Vec<String>, String> {
179        let plugin_metadata = self.plugin_metadata.read().unwrap();
180        let mut result = Vec::new();
181        let mut visited = std::collections::HashSet::new();
182        let mut visiting = std::collections::HashSet::new();
183
184        fn visit(
185            name: &str,
186            plugin_metadata: &HashMap<String, PluginMetadata>,
187            result: &mut Vec<String>,
188            visited: &mut std::collections::HashSet<String>,
189            visiting: &mut std::collections::HashSet<String>,
190        ) -> Result<(), String> {
191            if visiting.contains(name) {
192                return Err(format!("Circular dependency detected involving '{}'", name));
193            }
194
195            if visited.contains(name) {
196                return Ok(());
197            }
198
199            visiting.insert(name.to_string());
200
201            if let Some(metadata) = plugin_metadata.get(name) {
202                for dependency in &metadata.dependencies {
203                    visit(dependency, plugin_metadata, result, visited, visiting)?;
204                }
205            }
206
207            visiting.remove(name);
208            visited.insert(name.to_string());
209            result.push(name.to_string());
210
211            Ok(())
212        }
213
214        for name in plugin_names {
215            visit(
216                name,
217                &plugin_metadata,
218                &mut result,
219                &mut visited,
220                &mut visiting,
221            )?;
222        }
223
224        Ok(result)
225    }
226
227    /// Clear all plugins
228    pub fn clear(&self) {
229        let mut plugins = self.plugins.write().unwrap();
230        plugins.clear();
231
232        let mut plugin_metadata = self.plugin_metadata.write().unwrap();
233        plugin_metadata.clear();
234
235        let mut type_mappings = self.type_mappings.write().unwrap();
236        type_mappings.clear();
237    }
238
239    /// Get plugin count
240    pub fn count(&self) -> usize {
241        let plugins = self.plugins.read().unwrap();
242        plugins.len()
243    }
244
245    /// Helper function to parse node type from string
246    fn parse_node_type(&self, type_str: &str) -> Result<NodeType, String> {
247        match type_str {
248            "Catalog" => Ok(NodeType::Catalog),
249            "Pages" => Ok(NodeType::Pages),
250            "Page" => Ok(NodeType::Page),
251            "ContentStream" => Ok(NodeType::ContentStream),
252            "Font" => Ok(NodeType::Font),
253            "Type1Font" => Ok(NodeType::Type1Font),
254            "TrueTypeFont" => Ok(NodeType::TrueTypeFont),
255            "Type3Font" => Ok(NodeType::Type3Font),
256            "Image" => Ok(NodeType::Image),
257            "Annotation" => Ok(NodeType::Annotation),
258            "Outline" => Ok(NodeType::Outline),
259            "Action" => Ok(NodeType::Action),
260            "Encryption" => Ok(NodeType::Encryption),
261            "Metadata" => Ok(NodeType::Metadata),
262            "Structure" => Ok(NodeType::Structure),
263            "Form" => Ok(NodeType::Form),
264            "JavaScript" => Ok(NodeType::JavaScript),
265            "Multimedia" => Ok(NodeType::Multimedia),
266            "ColorSpace" => Ok(NodeType::ColorSpace),
267            "Pattern" => Ok(NodeType::Pattern),
268            "Shading" => Ok(NodeType::Shading),
269            "XObject" => Ok(NodeType::XObject),
270            "EmbeddedFile" => Ok(NodeType::EmbeddedFile),
271            "Other" => Ok(NodeType::Other),
272            _ => Err(format!("Unknown node type: {}", type_str)),
273        }
274    }
275}
276
277impl Default for PluginRegistry {
278    fn default() -> Self {
279        Self::new()
280    }
281}
282
283impl Clone for PluginRegistry {
284    fn clone(&self) -> Self {
285        Self {
286            plugins: Arc::clone(&self.plugins),
287            plugin_metadata: Arc::clone(&self.plugin_metadata),
288            type_mappings: Arc::clone(&self.type_mappings),
289        }
290    }
291}