use crate::{
event::EventDispatcher,
plugin::PluginOptions,
strategy::StrategyOptions,
units::error::{BError, MyError},
};
use serde_json::Value;
use std::collections::HashMap;
type PluginsMap = HashMap<String, Box<dyn PluginOptions>>;
type StrategysMap = HashMap<String, Box<dyn StrategyOptions>>;
pub struct Engine {
pub event: EventDispatcher,
plugins: PluginsMap,
strategys: StrategysMap,
}
impl Engine {
pub fn new() -> Self {
Self {
event: EventDispatcher::new(),
plugins: HashMap::new(),
strategys: HashMap::new(),
}
}
pub fn get_plugins(&self) -> &PluginsMap {
&self.plugins
}
pub fn plugin_data(&self, name: &str) -> Option<Value> {
if let Some(x) = self.plugins.get(name) {
x.get_data()
} else {
println!("插件{}不存在", name);
None
}
}
pub fn get_strategys(&self) -> &StrategysMap {
&self.strategys
}
pub fn strategy_data(&self, name: &str) -> Option<Value> {
if let Some(x) = self.strategys.get(name) {
x.get_data()
} else {
println!("策略{}不存在", name);
None
}
}
pub fn install<P: PluginOptions + 'static>(&mut self, plugin: P) -> MyError<()> {
let name = plugin.name();
if !self.plugins.contains_key(name) {
let mut deps: Vec<&str> = Vec::new();
for dep in plugin.deps() {
if !self.plugins.contains_key(dep) {
deps.push(dep);
}
}
if !deps.is_empty() {
return Err(BError::with_msg(&format!(
"安装插件 '{}' 出错:依赖插件 '{}' 不存在",
name,
deps.join(",")
)));
}
let mut plugin_box = Box::new(plugin);
plugin_box.install(self);
self.plugins
.insert(plugin_box.name().to_string(), plugin_box);
}
Ok(())
}
pub fn uninstall(&mut self, plugin_name: &str) {
if let Some(mut plugin) = self.plugins.remove(plugin_name) {
let mut strategies = Vec::new();
for (_, strategy) in self.strategys.iter() {
if strategy.condition().contains(&plugin_name) {
strategies.push(strategy.name().to_string());
}
}
for strategy_name in strategies {
self.rollback(&strategy_name);
}
let mut plugins = Vec::new();
for (_, plugin) in self.plugins.iter() {
if plugin.deps().contains(&plugin_name) {
plugins.push(plugin.name().to_string());
}
}
for plugin_name in plugins {
self.uninstall(&plugin_name);
}
plugin.dispose(self);
} else {
println!("插件 {} 不存在", plugin_name)
}
}
pub fn exec<S: StrategyOptions + 'static>(&mut self, strategy: S) -> MyError<()> {
let name = strategy.name();
if !self.strategys.contains_key(name) {
let mut plugins: Vec<&str> = Vec::new();
for plugin in strategy.condition() {
if !self.plugins.contains_key(plugin) {
plugins.push(plugin);
}
}
if plugins.len() > 0 {
return Err(BError::with_msg(&format!(
"执行策略 '{}' 出错:依赖插件 '{}' 不存在",
name,
plugins.join(",")
)));
}
strategy.exec(self);
self.strategys
.insert(strategy.name().to_string(), Box::new(strategy));
}
Ok(())
}
pub fn rollback(&mut self, strategy_name: &str) {
if let Some(mut strategy) = self.strategys.remove(strategy_name) {
strategy.rollback(self);
} else {
println!("策略 {} 不存在", strategy_name)
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_fun() {}
}