use crate::engine::functions::{MapConfig, ValidationConfig};
use crate::engine::{FunctionConfig, Workflow};
use datalogic_rs::{CompiledLogic, DataLogic};
use log::{debug, error};
use serde_json::Value;
use std::collections::HashMap;
use std::sync::Arc;
pub struct LogicCompiler {
datalogic: Arc<DataLogic>,
logic_cache: Vec<Arc<CompiledLogic>>,
}
impl Default for LogicCompiler {
fn default() -> Self {
Self::new()
}
}
impl LogicCompiler {
pub fn new() -> Self {
Self {
datalogic: Arc::new(DataLogic::with_preserve_structure()),
logic_cache: Vec::new(),
}
}
pub fn datalogic(&self) -> Arc<DataLogic> {
Arc::clone(&self.datalogic)
}
pub fn logic_cache(&self) -> &Vec<Arc<CompiledLogic>> {
&self.logic_cache
}
pub fn into_parts(self) -> (Arc<DataLogic>, Vec<Arc<CompiledLogic>>) {
(self.datalogic, self.logic_cache)
}
pub fn compile_workflows(&mut self, workflows: Vec<Workflow>) -> HashMap<String, Workflow> {
let mut workflow_map = HashMap::new();
for mut workflow in workflows {
if let Err(e) = workflow.validate() {
error!("Invalid workflow {}: {:?}", workflow.id, e);
continue;
}
debug!(
"Compiling condition for workflow {}: {:?}",
workflow.id, workflow.condition
);
match self.compile_logic(&workflow.condition) {
Ok(index) => {
workflow.condition_index = index;
debug!(
"Workflow {} condition compiled at index {:?}",
workflow.id, index
);
self.compile_workflow_tasks(&mut workflow);
workflow_map.insert(workflow.id.clone(), workflow);
}
Err(e) => {
error!(
"Failed to parse condition for workflow {}: {:?}",
workflow.id, e
);
}
}
}
workflow_map
}
fn compile_workflow_tasks(&mut self, workflow: &mut Workflow) {
for task in &mut workflow.tasks {
debug!(
"Compiling condition for task {} in workflow {}: {:?}",
task.id, workflow.id, task.condition
);
match self.compile_logic(&task.condition) {
Ok(index) => {
task.condition_index = index;
debug!("Task {} condition compiled at index {:?}", task.id, index);
}
Err(e) => {
error!(
"Failed to parse condition for task {} in workflow {}: {:?}",
task.id, workflow.id, e
);
}
}
self.compile_function_logic(&mut task.function, &task.id, &workflow.id);
}
}
fn compile_function_logic(
&mut self,
function: &mut FunctionConfig,
task_id: &str,
workflow_id: &str,
) {
match function {
FunctionConfig::Map { input, .. } => {
self.compile_map_logic(input, task_id, workflow_id);
}
FunctionConfig::Validation { input, .. } => {
self.compile_validation_logic(input, task_id, workflow_id);
}
_ => {
}
}
}
fn compile_map_logic(&mut self, config: &mut MapConfig, task_id: &str, workflow_id: &str) {
for mapping in &mut config.mappings {
debug!(
"Compiling map logic for task {} in workflow {}: {:?}",
task_id, workflow_id, mapping.logic
);
match self.compile_logic(&mapping.logic) {
Ok(index) => {
mapping.logic_index = index;
debug!(
"Map logic for task {} compiled at index {:?}",
task_id, index
);
}
Err(e) => {
error!(
"Failed to parse map logic for task {} in workflow {}: {:?}",
task_id, workflow_id, e
);
}
}
}
}
fn compile_validation_logic(
&mut self,
config: &mut ValidationConfig,
task_id: &str,
workflow_id: &str,
) {
for rule in &mut config.rules {
debug!(
"Compiling validation logic for task {} in workflow {}: {:?}",
task_id, workflow_id, rule.logic
);
match self.compile_logic(&rule.logic) {
Ok(index) => {
rule.logic_index = index;
debug!(
"Validation logic for task {} compiled at index {:?}",
task_id, index
);
}
Err(e) => {
error!(
"Failed to parse validation logic for task {} in workflow {}: {:?}",
task_id, workflow_id, e
);
}
}
}
}
fn compile_logic(&mut self, logic: &Value) -> Result<Option<usize>, String> {
match self.datalogic.compile(logic) {
Ok(compiled) => {
let index = self.logic_cache.len();
self.logic_cache.push(compiled);
Ok(Some(index))
}
Err(e) => Err(format!("Failed to compile logic: {}", e)),
}
}
}