reactive_graph_graphql_schema/query/instances/
flow_instance.rs

1use std::sync::Arc;
2
3use async_graphql::Context;
4use async_graphql::Object;
5use async_graphql::Result;
6use reactive_graph_graph::InvalidFlowInstanceError;
7use reactive_graph_reactive_model_impl::ReactiveFlow;
8use reactive_graph_type_system_api::EntityTypeManager;
9use uuid::Uuid;
10
11use crate::query::GraphQLEntityInstance;
12use crate::query::GraphQLEntityType;
13use crate::query::GraphQLRelationInstance;
14
15pub struct GraphQLFlowInstance {
16    flow_instance: ReactiveFlow,
17}
18
19/// A flow is a container for entity instances and relation instances.
20///
21/// A flow is strictly associated with a wrapper entity instance. The properties
22/// of the wrapper entity instance are the properties of the flow.
23///
24/// Additionally, flows can be nested -  from the perspective of the outer flow
25/// the inner flow acts like an entity instance. The wrapper entity instance of
26/// the inner flow is the interface which can be accessed by the outer flow.
27///
28/// Entity instances and relation instances can be shared with multiple flows.
29///
30/// It's even possible to connect entity instances from different flows with relation
31/// instances.
32#[Object(name = "FlowInstance")]
33impl GraphQLFlowInstance {
34    /// The id of the flow corresponds to the id of the wrapper entity instance
35    ///
36    /// This means the vector of entity instances must contain an instance with
37    /// the id of the flow.
38    async fn id(&self) -> Uuid {
39        self.flow_instance.id
40    }
41
42    /// The label of the entity instance if available.
43    async fn label(&self) -> Option<String> {
44        self.flow_instance
45            .get_wrapper_entity_instance()
46            .unwrap()
47            .properties
48            .get("label")
49            .and_then(|property_instance| property_instance.as_string())
50    }
51
52    /// The name of the flow instance.
53    async fn name(&self) -> String {
54        self.flow_instance.name.clone()
55    }
56
57    /// Textual description of the flow instance.
58    async fn description(&self) -> String {
59        self.flow_instance.description.clone()
60    }
61
62    /// The (entity-) type of the flow.
63    #[graphql(name = "type")]
64    async fn entity_type(&self, context: &Context<'_>) -> Result<GraphQLEntityType> {
65        let entity_type_manager = context.data::<Arc<dyn EntityTypeManager + Send + Sync>>()?;
66        entity_type_manager
67            .get(&self.flow_instance.ty)
68            .map(Into::into)
69            .ok_or(InvalidFlowInstanceError::EntityTypeDoesNotExist(self.flow_instance.ty.clone()).into())
70    }
71
72    /// The entity instance which is the wrapper for this flow.
73    async fn wrapper(&self) -> Option<GraphQLEntityInstance> {
74        self.flow_instance.get_wrapper_entity_instance().map(|e| e.into())
75    }
76
77    /// The entity instances contained by this flow.
78    async fn entities(&self) -> Vec<GraphQLEntityInstance> {
79        let reader = self.flow_instance.entity_instances.read().unwrap();
80        reader
81            .values()
82            .map(|reactive_entity| {
83                let entity_instance: GraphQLEntityInstance = reactive_entity.clone().into();
84                entity_instance
85            })
86            .collect()
87    }
88
89    /// The relation instances contained by this flow.
90    async fn relations(&self) -> Vec<GraphQLRelationInstance> {
91        let reader = self.flow_instance.relation_instances.read().unwrap();
92        reader
93            .values()
94            .map(|reactive_relation| {
95                let relation_instance: GraphQLRelationInstance = reactive_relation.clone().into();
96                relation_instance
97            })
98            .collect()
99    }
100}
101
102impl From<ReactiveFlow> for GraphQLFlowInstance {
103    fn from(flow: ReactiveFlow) -> Self {
104        GraphQLFlowInstance { flow_instance: flow }
105    }
106}