|
@@ -4,7 +4,8 @@ from core.workflow.entities.base_node_data_entities import BaseNodeData
|
|
|
from core.workflow.entities.node_entities import NodeRunResult, NodeType
|
|
|
from core.workflow.entities.variable_pool import VariablePool
|
|
|
from core.workflow.nodes.base_node import BaseNode
|
|
|
-from core.workflow.nodes.if_else.entities import IfElseNodeData
|
|
|
+from core.workflow.nodes.if_else.entities import Condition, IfElseNodeData
|
|
|
+from core.workflow.utils.variable_template_parser import VariableTemplateParser
|
|
|
from models.workflow import WorkflowNodeExecutionStatus
|
|
|
|
|
|
|
|
@@ -29,68 +30,46 @@ class IfElseNode(BaseNode):
|
|
|
"condition_results": []
|
|
|
}
|
|
|
|
|
|
+ input_conditions = []
|
|
|
+ final_result = False
|
|
|
+ selected_case_id = None
|
|
|
try:
|
|
|
- logical_operator = node_data.logical_operator
|
|
|
- input_conditions = []
|
|
|
- for condition in node_data.conditions:
|
|
|
- actual_value = variable_pool.get_variable_value(
|
|
|
- variable_selector=condition.variable_selector
|
|
|
+ # Check if the new cases structure is used
|
|
|
+ if node_data.cases:
|
|
|
+ for case in node_data.cases:
|
|
|
+ input_conditions, group_result = self.process_conditions(variable_pool, case.conditions)
|
|
|
+ # Apply the logical operator for the current case
|
|
|
+ final_result = all(group_result) if case.logical_operator == "and" else any(group_result)
|
|
|
+
|
|
|
+ process_datas["condition_results"].append(
|
|
|
+ {
|
|
|
+ "group": case.model_dump(),
|
|
|
+ "results": group_result,
|
|
|
+ "final_result": final_result,
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ # Break if a case passes (logical short-circuit)
|
|
|
+ if final_result:
|
|
|
+ selected_case_id = case.case_id # Capture the ID of the passing case
|
|
|
+ break
|
|
|
+
|
|
|
+ else:
|
|
|
+ # Fallback to old structure if cases are not defined
|
|
|
+ input_conditions, group_result = self.process_conditions(variable_pool, node_data.conditions)
|
|
|
+
|
|
|
+ final_result = all(group_result) if node_data.logical_operator == "and" else any(group_result)
|
|
|
+
|
|
|
+ process_datas["condition_results"].append(
|
|
|
+ {
|
|
|
+ "group": "default",
|
|
|
+ "results": group_result,
|
|
|
+ "final_result": final_result
|
|
|
+ }
|
|
|
)
|
|
|
|
|
|
- expected_value = condition.value
|
|
|
-
|
|
|
- input_conditions.append({
|
|
|
- "actual_value": actual_value,
|
|
|
- "expected_value": expected_value,
|
|
|
- "comparison_operator": condition.comparison_operator
|
|
|
- })
|
|
|
-
|
|
|
node_inputs["conditions"] = input_conditions
|
|
|
|
|
|
- for input_condition in input_conditions:
|
|
|
- actual_value = input_condition["actual_value"]
|
|
|
- expected_value = input_condition["expected_value"]
|
|
|
- comparison_operator = input_condition["comparison_operator"]
|
|
|
-
|
|
|
- if comparison_operator == "contains":
|
|
|
- compare_result = self._assert_contains(actual_value, expected_value)
|
|
|
- elif comparison_operator == "not contains":
|
|
|
- compare_result = self._assert_not_contains(actual_value, expected_value)
|
|
|
- elif comparison_operator == "start with":
|
|
|
- compare_result = self._assert_start_with(actual_value, expected_value)
|
|
|
- elif comparison_operator == "end with":
|
|
|
- compare_result = self._assert_end_with(actual_value, expected_value)
|
|
|
- elif comparison_operator == "is":
|
|
|
- compare_result = self._assert_is(actual_value, expected_value)
|
|
|
- elif comparison_operator == "is not":
|
|
|
- compare_result = self._assert_is_not(actual_value, expected_value)
|
|
|
- elif comparison_operator == "empty":
|
|
|
- compare_result = self._assert_empty(actual_value)
|
|
|
- elif comparison_operator == "not empty":
|
|
|
- compare_result = self._assert_not_empty(actual_value)
|
|
|
- elif comparison_operator == "=":
|
|
|
- compare_result = self._assert_equal(actual_value, expected_value)
|
|
|
- elif comparison_operator == "≠":
|
|
|
- compare_result = self._assert_not_equal(actual_value, expected_value)
|
|
|
- elif comparison_operator == ">":
|
|
|
- compare_result = self._assert_greater_than(actual_value, expected_value)
|
|
|
- elif comparison_operator == "<":
|
|
|
- compare_result = self._assert_less_than(actual_value, expected_value)
|
|
|
- elif comparison_operator == "≥":
|
|
|
- compare_result = self._assert_greater_than_or_equal(actual_value, expected_value)
|
|
|
- elif comparison_operator == "≤":
|
|
|
- compare_result = self._assert_less_than_or_equal(actual_value, expected_value)
|
|
|
- elif comparison_operator == "null":
|
|
|
- compare_result = self._assert_null(actual_value)
|
|
|
- elif comparison_operator == "not null":
|
|
|
- compare_result = self._assert_not_null(actual_value)
|
|
|
- else:
|
|
|
- continue
|
|
|
-
|
|
|
- process_datas["condition_results"].append({
|
|
|
- **input_condition,
|
|
|
- "result": compare_result
|
|
|
- })
|
|
|
except Exception as e:
|
|
|
return NodeRunResult(
|
|
|
status=WorkflowNodeExecutionStatus.FAILED,
|
|
@@ -99,21 +78,106 @@ class IfElseNode(BaseNode):
|
|
|
error=str(e)
|
|
|
)
|
|
|
|
|
|
- if logical_operator == "and":
|
|
|
- compare_result = False not in [condition["result"] for condition in process_datas["condition_results"]]
|
|
|
- else:
|
|
|
- compare_result = True in [condition["result"] for condition in process_datas["condition_results"]]
|
|
|
+ outputs = {
|
|
|
+ "result": final_result
|
|
|
+ }
|
|
|
+ if node_data.cases:
|
|
|
+ outputs["selected_case_id"] = selected_case_id
|
|
|
|
|
|
- return NodeRunResult(
|
|
|
+ data = NodeRunResult(
|
|
|
status=WorkflowNodeExecutionStatus.SUCCEEDED,
|
|
|
inputs=node_inputs,
|
|
|
process_data=process_datas,
|
|
|
- edge_source_handle="false" if not compare_result else "true",
|
|
|
- outputs={
|
|
|
- "result": compare_result
|
|
|
- }
|
|
|
+ edge_source_handle=selected_case_id if selected_case_id else "false", # Use case ID or 'default'
|
|
|
+ outputs=outputs
|
|
|
)
|
|
|
|
|
|
+ return data
|
|
|
+
|
|
|
+ def evaluate_condition(
|
|
|
+ self, actual_value: Optional[str | list], expected_value: str, comparison_operator: str
|
|
|
+ ) -> bool:
|
|
|
+ """
|
|
|
+ Evaluate condition
|
|
|
+ :param actual_value: actual value
|
|
|
+ :param expected_value: expected value
|
|
|
+ :param comparison_operator: comparison operator
|
|
|
+
|
|
|
+ :return: bool
|
|
|
+ """
|
|
|
+ if comparison_operator == "contains":
|
|
|
+ return self._assert_contains(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "not contains":
|
|
|
+ return self._assert_not_contains(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "start with":
|
|
|
+ return self._assert_start_with(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "end with":
|
|
|
+ return self._assert_end_with(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "is":
|
|
|
+ return self._assert_is(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "is not":
|
|
|
+ return self._assert_is_not(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "empty":
|
|
|
+ return self._assert_empty(actual_value)
|
|
|
+ elif comparison_operator == "not empty":
|
|
|
+ return self._assert_not_empty(actual_value)
|
|
|
+ elif comparison_operator == "=":
|
|
|
+ return self._assert_equal(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "≠":
|
|
|
+ return self._assert_not_equal(actual_value, expected_value)
|
|
|
+ elif comparison_operator == ">":
|
|
|
+ return self._assert_greater_than(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "<":
|
|
|
+ return self._assert_less_than(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "≥":
|
|
|
+ return self._assert_greater_than_or_equal(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "≤":
|
|
|
+ return self._assert_less_than_or_equal(actual_value, expected_value)
|
|
|
+ elif comparison_operator == "null":
|
|
|
+ return self._assert_null(actual_value)
|
|
|
+ elif comparison_operator == "not null":
|
|
|
+ return self._assert_not_null(actual_value)
|
|
|
+ else:
|
|
|
+ raise ValueError(f"Invalid comparison operator: {comparison_operator}")
|
|
|
+
|
|
|
+ def process_conditions(self, variable_pool: VariablePool, conditions: list[Condition]):
|
|
|
+ input_conditions = []
|
|
|
+ group_result = []
|
|
|
+
|
|
|
+ for condition in conditions:
|
|
|
+ actual_value = variable_pool.get_variable_value(
|
|
|
+ variable_selector=condition.variable_selector
|
|
|
+ )
|
|
|
+
|
|
|
+ if condition.value is not None:
|
|
|
+ variable_template_parser = VariableTemplateParser(template=condition.value)
|
|
|
+ expected_value = variable_template_parser.extract_variable_selectors()
|
|
|
+ variable_selectors = variable_template_parser.extract_variable_selectors()
|
|
|
+ if variable_selectors:
|
|
|
+ for variable_selector in variable_selectors:
|
|
|
+ value = variable_pool.get_variable_value(
|
|
|
+ variable_selector=variable_selector.value_selector
|
|
|
+ )
|
|
|
+ expected_value = variable_template_parser.format({variable_selector.variable: value})
|
|
|
+ else:
|
|
|
+ expected_value = condition.value
|
|
|
+ else:
|
|
|
+ expected_value = None
|
|
|
+
|
|
|
+ comparison_operator = condition.comparison_operator
|
|
|
+ input_conditions.append(
|
|
|
+ {
|
|
|
+ "actual_value": actual_value,
|
|
|
+ "expected_value": expected_value,
|
|
|
+ "comparison_operator": comparison_operator
|
|
|
+ }
|
|
|
+ )
|
|
|
+
|
|
|
+ result = self.evaluate_condition(actual_value, expected_value, comparison_operator)
|
|
|
+ group_result.append(result)
|
|
|
+
|
|
|
+ return input_conditions, group_result
|
|
|
+
|
|
|
def _assert_contains(self, actual_value: Optional[str | list], expected_value: str) -> bool:
|
|
|
"""
|
|
|
Assert contains
|