reactive_graph_graphql_schema/query/instances/
relation_instance.rs

1use std::sync::Arc;
2
3use async_graphql::Context;
4use async_graphql::Object;
5use async_graphql::Result;
6use reactive_graph_behaviour_service_api::RelationBehaviourRegistry;
7use reactive_graph_behaviour_service_api::RelationComponentBehaviourRegistry;
8use reactive_graph_reactive_model_impl::ReactiveRelation;
9use reactive_graph_type_system_api::ComponentManager;
10use reactive_graph_type_system_api::RelationTypeManager;
11
12use crate::query::GraphQLComponent;
13use crate::query::GraphQLComponentBehaviour;
14use crate::query::GraphQLEntityInstance;
15use crate::query::GraphQLPropertyInstance;
16use crate::query::GraphQLRelationBehaviour;
17use crate::query::GraphQLRelationType;
18
19pub struct GraphQLRelationInstance {
20    relation_instance: ReactiveRelation,
21}
22
23/// Relation instances are edges from an outbound entity instance to an
24/// inbound entity instance.
25///
26/// The relation instance is of a relation type. The relation type defines
27/// the entity types of the outbound entity instance and the inbound entity
28/// instance. Furthermore, the relation type defines which properties
29/// (name, data type, socket type) a relation instance have to have.
30///
31/// In contrast to the relation type, the relation instance stores values/
32/// documents in its properties.
33#[Object(name = "RelationInstance")]
34impl GraphQLRelationInstance {
35    /// The outbound entity instance.
36    ///
37    /// You can use this in order to navigate from the outbound entity instance to the inbound
38    /// entity instance or vice versa.
39    async fn outbound(&self) -> GraphQLEntityInstance {
40        self.relation_instance.outbound.clone().into()
41    }
42
43    /// The relation type.
44    #[graphql(name = "type")]
45    async fn relation_type(&self, context: &Context<'_>) -> Option<GraphQLRelationType> {
46        context
47            .data::<Arc<dyn RelationTypeManager + Send + Sync>>()
48            .ok()?
49            .get(&self.relation_instance.relation_type_id())
50            .map(|r| r.into())
51    }
52
53    /// The instance id of the relation instance type.
54    async fn instance_id(&self) -> String {
55        self.relation_instance.ty.instance_id()
56    }
57
58    /// The inbound entity instance.
59    ///
60    /// You can use this in order to navigate from the inbound entity instance to the outbound
61    /// entity instance or vice versa.
62    async fn inbound(&self) -> GraphQLEntityInstance {
63        self.relation_instance.inbound.clone().into()
64    }
65
66    /// The name of the relation instance.
67    async fn name(&self) -> String {
68        self.relation_instance.name.clone()
69    }
70
71    /// Textual description of the relation instance.
72    async fn description(&self) -> String {
73        self.relation_instance.description.clone()
74    }
75
76    /// The properties of then relation instance.
77    ///
78    /// Each property is represented by its name (String) and it's value. The value is
79    /// a representation of a JSON. Therefore, the value can be boolean, number, string,
80    /// array or an object. For more information about the data types please look at
81    /// https://docs.serde.rs/serde_json/value/enum.Value.html
82    async fn properties(
83        &self,
84        #[graphql(desc = "Filters by property name.")] name: Option<String>,
85        #[graphql(desc = "Filters by property names")] names: Option<Vec<String>>,
86        #[graphql(desc = "If true, the properties are sorted by name")] sort: Option<bool>,
87    ) -> Vec<GraphQLPropertyInstance> {
88        let mut properties: Vec<GraphQLPropertyInstance> = self
89            .relation_instance
90            .properties
91            .iter()
92            .filter(|property_instance| name.is_none() || name.clone().unwrap() == property_instance.key().as_str())
93            .filter(|property_instance| names.is_none() || names.clone().unwrap().contains(property_instance.key()))
94            .map(|property_instance| {
95                GraphQLPropertyInstance::new_relation_property(
96                    self.relation_instance.relation_type_id(),
97                    property_instance.key().clone(),
98                    property_instance.get(),
99                )
100            })
101            .collect();
102        if sort.unwrap_or_default() {
103            properties.sort_by(|a, b| a.name.cmp(&b.name));
104        }
105        properties
106    }
107
108    /// The components which have been actually applied on the relation instance including
109    /// components which have been added after creation.
110    async fn components(&self, context: &Context<'_>) -> Vec<GraphQLComponent> {
111        match context.data::<Arc<dyn ComponentManager + Send + Sync>>() {
112            Ok(component_manager) => self
113                .relation_instance
114                .components
115                .iter()
116                .map(|p| p.key().clone())
117                .filter_map(|component_name| {
118                    component_manager.get(&component_name).map(|component| {
119                        let component: GraphQLComponent = component.into();
120                        component
121                    })
122                })
123                .collect(),
124            Err(_) => Vec::new(),
125        }
126    }
127
128    /// List of relation behaviours which have been actually applied on the relation instance
129    /// including behaviours which have been applied after creation.
130    async fn behaviours(&self, context: &Context<'_>) -> Result<Vec<GraphQLRelationBehaviour>> {
131        let relation_behaviour_registry = context.data::<Arc<dyn RelationBehaviourRegistry + Send + Sync>>()?;
132        Ok(self
133            .relation_instance
134            .behaviours
135            .iter()
136            .filter_map(move |p| {
137                let behaviour_ty = p.key();
138                relation_behaviour_registry
139                    .get_by_behaviour_type(behaviour_ty)
140                    .map(GraphQLRelationBehaviour::from)
141            })
142            .collect())
143    }
144
145    /// List of component behaviours which have been actually applied on the entity instance
146    /// including behaviours which have been applied after creation.
147    async fn component_behaviours(&self, context: &Context<'_>) -> Result<Vec<GraphQLComponentBehaviour>> {
148        let relation_component_behaviour_registry = context.data::<Arc<dyn RelationComponentBehaviourRegistry + Send + Sync>>()?;
149        Ok(self
150            .relation_instance
151            .behaviours
152            .iter()
153            .filter_map(move |p| {
154                let behaviour_ty = p.key();
155                relation_component_behaviour_registry
156                    .get_by_behaviour_type(behaviour_ty)
157                    .map(GraphQLComponentBehaviour::from)
158            })
159            .collect())
160    }
161}
162
163impl From<ReactiveRelation> for GraphQLRelationInstance {
164    fn from(relation_instance: ReactiveRelation) -> Self {
165        GraphQLRelationInstance { relation_instance }
166    }
167}