cameleer-core 0.5.1

Core of Cameleer: exchanges, routes, EIPs, DSL, languages, core components
Documentation
//! The fluent Rust DSL.
//!
//! ```ignore
//! ctx.add_routes(|b| {
//!     b.from("timer:tick?period=1000")
//!         .route_id("ticker")
//!         .set_body(constant("Hello"))
//!         .to("log:out");
//! })?;
//! ```
//!
//! DSL methods are spread over several modules as `impl RouteDefinition` blocks:
//! - `core`: to, toD, setBody, setHeader, process, log, ...
//! - `routing`: filter, choice, split, aggregate, multicast, recipientList, ...
//! - `errors`: doTry/doCatch, onException, errorHandler, throttle, delay, ...
//! - `transform`: marshal/unmarshal and data formats, ...

pub mod core;
pub mod eips_extra;
pub mod errors;
pub mod routing;
pub mod saga;
pub mod transform;

use std::any::Any;
use std::collections::BTreeMap;

use crate::context::CamelContext;
use crate::error::Result;
use crate::model::RouteDefinition;

/// Customizer applied to each route definition of a builder when it is converted
/// (used for builder-scoped configuration such as global onException clauses).
pub type DefinitionCustomizer = Box<dyn Fn(&mut RouteDefinition) + Send + Sync>;

/// Collects route definitions.
pub struct RouteBuilder {
    ctx: CamelContext,
    routes: Vec<RouteDefinition>,
    /// Builder-scoped extension data.
    pub extensions: BTreeMap<String, Box<dyn Any + Send + Sync>>,
    /// Applied to every route of this builder in `into_definitions`.
    pub customizers: Vec<DefinitionCustomizer>,
    /// Extra routes generated by extensions (e.g. REST DSL) at conversion time.
    pub generators: Vec<Box<dyn FnOnce(&CamelContext) -> Result<Vec<RouteDefinition>> + Send>>,
}

impl RouteBuilder {
    pub fn new(ctx: CamelContext) -> Self {
        RouteBuilder { ctx, routes: Vec::new(), extensions: BTreeMap::new(), customizers: Vec::new(), generators: Vec::new() }
    }

    pub fn context(&self) -> &CamelContext {
        &self.ctx
    }

    /// Start a new route consuming from `uri`.
    pub fn from(&mut self, uri: impl Into<String>) -> &mut RouteDefinition {
        self.routes.push(RouteDefinition::new(uri));
        self.routes.last_mut().unwrap()
    }

    /// Add an already built route definition.
    pub fn add_route(&mut self, def: RouteDefinition) {
        self.routes.push(def);
    }

    pub fn routes(&self) -> &[RouteDefinition] {
        &self.routes
    }

    pub fn routes_mut(&mut self) -> &mut Vec<RouteDefinition> {
        &mut self.routes
    }

    pub fn extension_mut<T: Any + Send + Sync + Default>(&mut self, key: &str) -> &mut T {
        if !self.extensions.get(key).map(|b| b.is::<T>()).unwrap_or(false) {
            self.extensions.insert(key.to_string(), Box::new(T::default()));
        }
        self.extensions.get_mut(key).unwrap().downcast_mut::<T>().unwrap()
    }

    /// Finish all routes (closing open blocks) and apply customizers.
    pub fn into_definitions(self) -> Result<Vec<RouteDefinition>> {
        let RouteBuilder { ctx, mut routes, customizers, generators, .. } = self;
        for g in generators {
            routes.extend(g(&ctx)?);
        }
        for r in routes.iter_mut() {
            r.finish()?;
            for c in &customizers {
                c(r);
            }
        }
        Ok(routes)
    }
}