reactive_graph_graphql_schema/query/instances/
entity_instance.rs1use 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#[Object(name = "EntityInstance")]
35impl GraphQLEntityInstance {
36 #[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 async fn id(&self) -> Uuid {
47 self.entity_instance.id
48 }
49
50 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 async fn name(&self) -> String {
60 self.entity_instance.name.clone()
61 }
62
63 async fn description(&self) -> String {
65 self.entity_instance.description.clone()
66 }
67
68 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 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 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 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 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 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}