use std::collections::HashMap;
use crate::core::context::Context;
use crate::core::link::LegacyLink;
use crate::core::middleware::Middleware;
pub struct Chain {
links: HashMap<String, Box<dyn LegacyLink>>,
connections: Vec<(String, String, Box<dyn Fn(&Context) -> bool + Send + Sync>)>,
middlewares: Vec<Box<dyn Middleware>>,
}
impl Chain {
pub fn new() -> Self {
Self {
links: HashMap::new(),
connections: Vec::new(),
middlewares: Vec::new(),
}
}
pub fn add_link(&mut self, name: String, link: Box<dyn LegacyLink>) {
self.links.insert(name, link);
}
pub fn connect<F>(&mut self, source: String, target: String, condition: F)
where
F: Fn(&Context) -> bool + Send + Sync + 'static,
{
self.connections.push((source, target, Box::new(condition)));
}
pub fn use_middleware(&mut self, middleware: Box<dyn Middleware>) {
self.middlewares.push(middleware);
}
pub async fn run(&self, initial_ctx: Context) -> Result<Context, Box<dyn std::error::Error + Send + Sync>> {
let mut ctx = initial_ctx;
for mw in &self.middlewares {
mw.before(None, &ctx).await?;
}
for (_name, link) in &self.links {
for mw in &self.middlewares {
mw.before(Some(link.as_ref()), &ctx).await?;
}
ctx = link.call(ctx).await?;
for mw in &self.middlewares {
mw.after(Some(link.as_ref()), &ctx).await?;
}
}
for mw in &self.middlewares {
mw.after(None, &ctx).await?;
}
Ok(ctx)
}
pub fn links(&self) -> &HashMap<String, Box<dyn LegacyLink>> {
&self.links
}
pub fn connections(&self) -> &[(String, String, Box<dyn Fn(&Context) -> bool + Send + Sync>)] {
&self.connections
}
pub fn middlewares(&self) -> &[Box<dyn Middleware>] {
&self.middlewares
}
}
impl Default for Chain {
fn default() -> Self {
Self::new()
}
}