Skip to main content

bpmn_engine/activity/
plugin.rs

1//! Plugin System
2//!
3//! Plugin system for extending BPMN engine functionality.
4
5use crate::activity::{Activity, ActivityFactory};
6use crate::model::ProcessElement;
7use std::collections::HashMap;
8use std::sync::Arc;
9
10/// Plugin Trait
11///
12/// Trait for BPMN engine plugins.
13pub trait Plugin: Send + Sync + std::fmt::Debug {
14    /// Get plugin name
15    fn name(&self) -> &str;
16
17    /// Get plugin version
18    fn version(&self) -> &str;
19
20    /// Initialize the plugin
21    fn initialize(&mut self) -> Result<(), PluginError>;
22
23    /// Get custom activity factories provided by this plugin
24    fn get_activity_factories(&self) -> HashMap<String, Arc<dyn ActivityFactory>>;
25
26    /// Get custom activity types provided by this plugin
27    fn get_custom_activity_types(&self) -> Vec<String>;
28}
29
30/// Plugin Error
31#[derive(Debug, thiserror::Error)]
32pub enum PluginError {
33    #[error("Plugin initialization failed: {0}")]
34    InitializationFailed(String),
35    #[error("Plugin not found: {0}")]
36    NotFound(String),
37}
38
39/// Plugin Registry
40///
41/// Registry for managing BPMN engine plugins.
42pub struct PluginRegistry {
43    plugins: Arc<tokio::sync::RwLock<HashMap<String, Arc<dyn Plugin>>>>,
44    activity_factories: Arc<tokio::sync::RwLock<HashMap<String, Arc<dyn ActivityFactory>>>>,
45}
46
47impl PluginRegistry {
48    /// Create a new plugin registry
49    pub fn new() -> Self {
50        Self {
51            plugins: Arc::new(tokio::sync::RwLock::new(HashMap::new())),
52            activity_factories: Arc::new(tokio::sync::RwLock::new(HashMap::new())),
53        }
54    }
55
56    /// Register a plugin
57    pub async fn register(&self, plugin: Arc<dyn Plugin>) -> Result<(), PluginError> {
58        let plugin_name = plugin.name().to_string();
59        
60        // Initialize plugin
61        // Note: We need mutable access, but Arc doesn't allow that
62        // In a real implementation, we'd need to handle this differently
63        // For now, we'll assume plugins are initialized before registration
64
65        // Register plugin
66        {
67            let mut plugins = self.plugins.write().await;
68            plugins.insert(plugin_name.clone(), plugin.clone());
69        }
70
71        // Register activity factories from plugin
72        {
73            let mut factories = self.activity_factories.write().await;
74            for (activity_type, factory) in plugin.get_activity_factories() {
75                factories.insert(activity_type, factory);
76            }
77        }
78
79        Ok(())
80    }
81
82    /// Get activity factory for a custom activity type
83    pub async fn get_activity_factory(&self, activity_type: &str) -> Option<Arc<dyn ActivityFactory>> {
84        let factories = self.activity_factories.read().await;
85        factories.get(activity_type).cloned()
86    }
87
88    /// Get all registered plugins
89    pub async fn get_plugins(&self) -> Vec<Arc<dyn Plugin>> {
90        let plugins = self.plugins.read().await;
91        plugins.values().cloned().collect()
92    }
93}
94
95impl Default for PluginRegistry {
96    fn default() -> Self {
97        Self::new()
98    }
99}
100