reactive_graph_std_string/behaviour/entity/
templating.rs1use log::error;
2use reactive_graph_behaviour_model_api::behaviour_validator;
3use reactive_graph_behaviour_model_api::prelude::*;
4use reactive_graph_behaviour_model_impl::entity_behaviour;
5use reactive_graph_graph::prelude::*;
6use reactive_graph_reactive_model_impl::ReactiveEntity;
7use serde_json::Value;
8use serde_json::json;
9use tera::Context;
10use tera::Tera;
11use uuid::Uuid;
12
13use reactive_graph_std_result_model::ResultStringProperties::RESULT;
14use reactive_graph_std_string_model::TemplatingProperties::CONTEXT;
15use reactive_graph_std_string_model::TemplatingProperties::TEMPLATE;
16
17entity_behaviour!(Templating, TemplatingFactory, TemplatingFsm, TemplatingBehaviourTransitions, TemplatingValidator);
18
19behaviour_validator!(TemplatingValidator, Uuid, ReactiveEntity, TEMPLATE.as_ref(), CONTEXT.as_ref(), RESULT.as_ref());
20
21impl BehaviourInit<Uuid, ReactiveEntity> for TemplatingBehaviourTransitions {
22 fn init(&self) -> Result<(), BehaviourInitializationFailed> {
23 let template = self.reactive_instance.get(TEMPLATE).ok_or(BehaviourInitializationFailed {})?;
24 let context = self.reactive_instance.get(CONTEXT).ok_or(BehaviourInitializationFailed {})?;
25 self.reactive_instance.set(RESULT, render(&template, &context));
26 Ok(())
27 }
28}
29
30impl BehaviourConnect<Uuid, ReactiveEntity> for TemplatingBehaviourTransitions {
31 fn connect(&self) -> Result<(), BehaviourConnectFailed> {
32 let reactive_instance = self.reactive_instance.clone();
33 self.property_observers.observe_with_handle(CONTEXT.as_ref(), move |context: &Value| {
34 if let Some(template) = reactive_instance.get(TEMPLATE) {
35 reactive_instance.set(RESULT, render(&template, context));
36 }
37 });
38 let reactive_instance = self.reactive_instance.clone();
39 self.property_observers.observe_with_handle(TEMPLATE.as_ref(), move |template: &Value| {
40 if let Some(context) = reactive_instance.get(CONTEXT) {
41 reactive_instance.set(RESULT, render(template, &context));
42 }
43 });
44 Ok(())
45 }
46}
47
48impl BehaviourShutdown<Uuid, ReactiveEntity> for TemplatingBehaviourTransitions {}
49impl BehaviourTransitions<Uuid, ReactiveEntity> for TemplatingBehaviourTransitions {}
50
51fn render(template: &Value, context: &Value) -> Value {
52 match template.as_str() {
53 Some(template) => match Context::from_value(context.clone()) {
54 Ok(tera_context) => {
55 let mut tera = Tera::default();
56 tera.autoescape_on(vec![]);
57 match tera.render_str(template, &tera_context) {
58 Ok(rendered) => json!(rendered),
59 Err(e) => {
60 error!("Rendering Error: {}", e);
61 json!({
62 "error": "Rendering Error",
63 "message": format!("{}", e),
64 "template": template,
65 "context": context
66 })
67 }
68 }
69 }
70 Err(e) => {
71 error!("Rendering Error: {}", e);
72 json!({
73 "error": "Context Error",
74 "message": format!("{}", e),
75 "template": template,
76 "context": context
77 })
78 }
79 },
80 None => {
81 json!({
82 "error": "Template Error",
83 "message": "Template not a string",
84 "template": template,
85 "context": context
86 })
87 }
88 }
89}