Skip to main content

bpm_engine_runtime/
transition.rs

1//! Token transition helpers: move_token, evaluate_exclusive_gateway.
2
3use super::el;
4use bpm_engine_core::{EdgeCondition, Node, NodeId, Token, TokenMode, TokenStatus};
5use std::collections::HashMap;
6
7fn new_token(node_id: String, parallel_group_id: Option<String>) -> Token {
8    Token {
9        id: uuid::Uuid::new_v4().to_string(),
10        node_id,
11        status: TokenStatus::Ready,
12        mode: TokenMode::Forward,
13        version: 0,
14        attempt: 0,
15        parallel_group_id,
16        updated_at: None,
17    }
18}
19
20pub fn move_token(node: &Node) -> Vec<Token> {
21    node.outgoing_edges
22        .iter()
23        .map(|e| new_token(e.target.to_string(), None))
24        .collect()
25}
26
27pub fn move_token_with_group(node: &Node, parallel_group_id: String) -> Vec<Token> {
28    node.outgoing_edges
29        .iter()
30        .map(|e| new_token(e.target.to_string(), Some(parallel_group_id.clone())))
31        .collect()
32}
33
34pub fn evaluate_exclusive_gateway(
35    node: &Node,
36    variables: &HashMap<String, String>,
37) -> Option<Token> {
38    let mut default_target: Option<NodeId> = None;
39    for edge in &node.outgoing_edges {
40        match &edge.condition {
41            None => return Some(new_token(edge.target.to_string(), None)),
42            Some(EdgeCondition::Default) => default_target = Some(edge.target),
43            Some(EdgeCondition::VariableEq { key, value }) => {
44                if variables.get(key) == Some(value) {
45                    return Some(new_token(edge.target.to_string(), None));
46                }
47            }
48            Some(EdgeCondition::Expression(expr)) => {
49                if el::eval_condition(expr, variables).unwrap_or(false) {
50                    return Some(new_token(edge.target.to_string(), None));
51                }
52            }
53        }
54    }
55    default_target.map(|t| new_token(t.to_string(), None))
56}