reactive_graph_graphql_schema/query/instances/
entity_instance.rs

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