use derive_builder::Builder;
use serde::{Deserialize, Serialize};
pub use cala_types::param::*;
use cel_interpreter::CelExpression;
#[derive(Clone, Debug, Deserialize, Serialize, Builder)]
#[builder(build_fn(validate = "Self::validate"))]
pub struct NewParamDefinition {
#[builder(setter(into))]
pub(crate) name: String,
pub(crate) r#type: ParamDataType,
#[builder(setter(strip_option, name = "default_expr", into), default)]
pub(crate) default: Option<String>,
#[builder(setter(strip_option, into), default)]
pub(crate) description: Option<String>,
}
impl NewParamDefinition {
pub fn builder() -> NewParamDefinitionBuilder {
NewParamDefinitionBuilder::default()
}
pub fn default_expr(&self) -> Option<CelExpression> {
self.default
.as_ref()
.map(|v| v.parse().expect("Couldn't create default_expr"))
}
}
impl NewParamDefinitionBuilder {
fn validate(&self) -> Result<(), String> {
use es_entity::clock::Clock;
if let Some(Some(expr)) = self.default.as_ref() {
let expr = CelExpression::try_from(expr.as_str()).map_err(|e| e.to_string())?;
let specified_type = self.r#type.as_ref().unwrap();
specified_type
.coerce_value(
expr.evaluate(&crate::cel_context::initialize(Clock::handle().clone()))
.map_err(|e| format!("{e}"))?,
)
.map_err(|e| {
format!(
"Default expression does not match parameter type {specified_type:?}: {e}"
)
})?;
}
Ok(())
}
}
impl From<NewParamDefinition> for cala_types::tx_template::ParamDefinition {
fn from(param: NewParamDefinition) -> Self {
let default = param.default_expr();
cala_types::tx_template::ParamDefinition {
name: param.name,
r#type: param.r#type,
default,
description: param.description,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn build_param_definition() {
let definition = NewParamDefinition::builder()
.name("name")
.r#type(ParamDataType::Json)
.default_expr("{'key': 'value'}")
.build()
.unwrap();
assert_eq!(definition.name, "name");
}
#[test]
fn build_date_param_definition_with_default() {
let definition = NewParamDefinition::builder()
.name("effective")
.r#type(ParamDataType::Date)
.default_expr("date()")
.build()
.unwrap();
assert_eq!(definition.name, "effective");
}
}