dsntk_model_evaluator/
model_evaluator.rs1use crate::business_knowledge_model::BusinessKnowledgeModelEvaluator;
4use crate::decision::DecisionEvaluator;
5use crate::decision_service::DecisionServiceEvaluator;
6use crate::input_data::InputDataEvaluator;
7use crate::item_definition::ItemDefinitionEvaluator;
8use crate::model_builder::{EvaluatorBuilders, ModelBuilder};
9use crate::model_definitions::{DefKey, InvocableType, Invocables};
10use dsntk_common::Result;
11use dsntk_feel::context::FeelContext;
12use dsntk_feel::values::Value;
13use dsntk_feel::{value_null, Name};
14use dsntk_model::Definitions;
15use std::sync::Arc;
16
17pub struct ModelEvaluator {
19 input_data_evaluator: InputDataEvaluator,
21 item_definition_evaluator: ItemDefinitionEvaluator,
23 business_knowledge_model_evaluator: BusinessKnowledgeModelEvaluator,
25 decision_evaluator: DecisionEvaluator,
27 decision_service_evaluator: DecisionServiceEvaluator,
29 invocables: Invocables,
31 global_context: FeelContext,
33}
34
35impl From<ModelBuilder> for ModelEvaluator {
36 fn from(model_builder: ModelBuilder) -> Self {
38 let builders: EvaluatorBuilders = model_builder.into();
39 let mut global_context = FeelContext::default();
40 for (def_key, feel_type) in builders.information_item_types {
41 global_context.set_entry(&Name::from(def_key.id()), Value::FeelType(feel_type))
42 }
43 Self {
44 input_data_evaluator: builders.input_data_evaluator,
45 item_definition_evaluator: builders.item_definition_evaluator,
46 business_knowledge_model_evaluator: builders.business_knowledge_model_evaluator,
47 decision_evaluator: builders.decision_evaluator,
48 decision_service_evaluator: builders.decision_service_evaluator,
49 invocables: builders.invocables,
50 global_context,
51 }
52 }
53}
54
55impl ModelEvaluator {
56 pub fn new(definitions: &[Definitions]) -> Result<Arc<Self>> {
58 let mut model_builder = ModelBuilder::default();
59 definitions.iter().for_each(|definitions| model_builder.add_model(definitions));
60 model_builder.build()?;
61 let model_evaluator: Arc<ModelEvaluator> = Arc::new(model_builder.into());
62 model_evaluator.decision_service_evaluator.build_function_definitions(&Arc::clone(&model_evaluator));
63 Ok(model_evaluator)
64 }
65
66 pub fn input_data_evaluator(&self) -> &InputDataEvaluator {
68 &self.input_data_evaluator
69 }
70
71 pub fn item_definition_evaluator(&self) -> &ItemDefinitionEvaluator {
73 &self.item_definition_evaluator
74 }
75
76 pub fn business_knowledge_model_evaluator(&self) -> &BusinessKnowledgeModelEvaluator {
78 &self.business_knowledge_model_evaluator
79 }
80
81 pub fn decision_evaluator(&self) -> &DecisionEvaluator {
83 &self.decision_evaluator
84 }
85
86 pub fn decision_service_evaluator(&self) -> &DecisionServiceEvaluator {
88 &self.decision_service_evaluator
89 }
90
91 pub fn invocables(&self) -> &Invocables {
93 &self.invocables
94 }
95
96 pub fn evaluate_invocable(&self, model_namespace: &str, model_name: &str, invocable_name: &str, input_data: &FeelContext) -> Value {
98 let Some(invocable) = self.invocables.by_name(model_namespace, model_name, invocable_name) else {
99 return value_null!("invocable '{}' not found in namespace '{}'", invocable_name, model_namespace);
100 };
101 match invocable {
102 InvocableType::Decision(def_key) => {
103 self.evaluate_decision(def_key, input_data)
105 }
106 InvocableType::BusinessKnowledgeModel(def_key, output_variable_name) => {
107 self.evaluate_bkm(def_key, input_data, output_variable_name)
109 }
110 InvocableType::DecisionService(def_key) => {
111 self.evaluate_decision_service(def_key, input_data)
113 }
114 }
115 }
116
117 fn evaluate_decision(&self, def_key: &DefKey, input_data: &FeelContext) -> Value {
119 let mut evaluated_ctx = FeelContext::default();
120 if let Some(output_variable_name) = self.decision_evaluator.evaluate(def_key, &self.global_context, input_data, self, &mut evaluated_ctx) {
121 if let Some(output_value) = evaluated_ctx.get_entry(&output_variable_name) {
122 output_value.clone()
123 } else {
124 value_null!()
125 }
126 } else {
127 value_null!()
128 }
129 }
130
131 fn evaluate_bkm(&self, def_key: &DefKey, input_data: &FeelContext, output_variable_name: &Name) -> Value {
133 let mut evaluated_ctx = FeelContext::default();
134 self
135 .business_knowledge_model_evaluator
136 .evaluate(def_key, &self.global_context, input_data, self, &mut evaluated_ctx);
137 if let Some(Value::FunctionDefinition(parameters, body, _external, _, closure_ctx, result_type)) = evaluated_ctx.get_entry(output_variable_name) {
138 let mut parameters_ctx = FeelContext::default();
140 parameters_ctx.zip(closure_ctx);
141 for (name, _) in parameters {
142 if let Some(value) = input_data.get_entry(name) {
143 parameters_ctx.set_entry(name, value.to_owned());
144 }
145 }
146 parameters_ctx.zip(&evaluated_ctx);
147 let result = body.evaluate(¶meters_ctx.into());
148 result.coerced(result_type)
149 } else {
150 value_null!()
151 }
152 }
153
154 fn evaluate_decision_service(&self, def_key: &DefKey, input_data: &FeelContext) -> Value {
156 let mut evaluated_ctx = FeelContext::default();
157 if let Some(output_variable_name) = self
158 .decision_service_evaluator
159 .evaluate(def_key, &self.global_context, input_data, self, &mut evaluated_ctx)
160 {
161 if let Some(output_value) = evaluated_ctx.get_entry(&output_variable_name) {
162 output_value.clone()
163 } else {
164 value_null!()
165 }
166 } else {
167 value_null!()
168 }
169 }
170}