use std::sync::Arc;
use crate::builder::ExpressionDefinition;
use crate::error::Result;
use crate::impl_definition_boilerplate;
use crate::message::Exchange;
use crate::model::{ProcessorDefinition, RouteContext};
use crate::spi::Processor;
pub const SCRIPT_PROCESSOR_FACTORY: &str = "camelScriptProcessorFactory";
pub type ScriptProcessorFactory =
Box<dyn Fn(&str, &str, &std::collections::BTreeMap<String, String>) -> Option<Result<Arc<dyn Processor>>> + Send + Sync>;
pub struct ScriptDefinition {
pub id: Option<String>,
pub expression: ExpressionDefinition,
}
impl ScriptDefinition {
pub fn new(expression: impl Into<ExpressionDefinition>) -> Self {
ScriptDefinition { id: None, expression: expression.into() }
}
}
impl ProcessorDefinition for ScriptDefinition {
fn name(&self) -> &str {
"script"
}
fn label(&self) -> String {
format!("script[{:?}]", self.expression)
}
fn create_processor(&self, rc: &RouteContext) -> Result<Arc<dyn Processor>> {
if let ExpressionDefinition::Language { language, expression, options } = &self.expression {
if let Some(f) = rc.context.registry().lookup::<ScriptProcessorFactory>(SCRIPT_PROCESSOR_FACTORY) {
if let Some(p) = f(language, &rc.context.resolve_placeholders(expression)?, options) {
return p;
}
}
}
let e = self.expression.resolve_expression(&rc.context)?;
Ok(Arc::new(move |ex: &mut Exchange| {
e.evaluate(ex)?;
Ok(())
}))
}
impl_definition_boilerplate!();
}