reactive_graph_graphql_schema/query/instances/
properties.rs1use std::collections::HashMap;
2use std::sync::Arc;
3
4use async_graphql::Context;
5use async_graphql::InputObject;
6use async_graphql::Object;
7use serde::Deserialize;
8use serde::Serialize;
9use serde_json::Value;
10
11use reactive_graph_graph::EntityTypeId;
12use reactive_graph_graph::PropertyInstances;
13use reactive_graph_graph::PropertyTypes;
14use reactive_graph_graph::RelationTypeId;
15use reactive_graph_type_system_api::EntityTypeManager;
16use reactive_graph_type_system_api::RelationTypeManager;
17
18use crate::query::GraphQLPropertyType;
19
20#[derive(Serialize, Deserialize, Clone, Debug, Default)]
21pub enum GraphQLPropertyTypeContainer {
22 #[default]
23 None,
24 Entity(EntityTypeId),
25 Relation(RelationTypeId),
26}
27
28#[derive(Serialize, Deserialize, Clone, Debug, InputObject)]
29#[graphql(name = "PropertyInstanceDefinition")]
30pub struct GraphQLPropertyInstance {
31 #[graphql(skip)]
32 pub property_type_container: GraphQLPropertyTypeContainer,
33
34 pub name: String,
36
37 pub value: Value,
39}
40
41#[Object(name = "PropertyInstance")]
48impl GraphQLPropertyInstance {
49 async fn name(&self) -> String {
51 self.name.clone()
52 }
53
54 async fn value(&self) -> Value {
56 self.value.clone()
57 }
58
59 #[graphql(name = "type")]
61 async fn property_type(&self, context: &Context<'_>) -> Option<GraphQLPropertyType> {
62 let property_name = self.name.clone();
63 match &self.property_type_container {
64 GraphQLPropertyTypeContainer::None => None,
65 GraphQLPropertyTypeContainer::Entity(ty) => match context.data::<Arc<dyn EntityTypeManager + Send + Sync>>() {
66 Ok(entity_type_manager) => match entity_type_manager.get(ty) {
67 Some(entity_type) => entity_type
68 .properties
69 .iter()
70 .find(|property_type| property_type.name == property_name)
71 .map(|property_type| property_type.value().clone().into()),
72 None => None,
73 },
74 Err(_) => None,
75 },
76 GraphQLPropertyTypeContainer::Relation(ty) => match context.data::<Arc<dyn RelationTypeManager + Send + Sync>>() {
77 Ok(relation_type_manager) => match relation_type_manager.get(ty) {
78 Some(relation_type) => relation_type
79 .properties
80 .iter()
81 .find(|property_type| property_type.name == property_name)
82 .map(|property_type| property_type.value().clone().into()),
83 None => None,
84 },
85 Err(_) => None,
86 },
87 }
88 }
89}
90
91impl GraphQLPropertyInstance {
92 pub fn new_entity_property(ty: EntityTypeId, name: String, value: Value) -> Self {
93 GraphQLPropertyInstance {
94 property_type_container: GraphQLPropertyTypeContainer::Entity(ty),
95 name,
96 value,
97 }
98 }
99
100 pub fn new_relation_property(ty: RelationTypeId, name: String, value: Value) -> Self {
102 GraphQLPropertyInstance {
103 property_type_container: GraphQLPropertyTypeContainer::Relation(ty),
104 name,
105 value,
106 }
107 }
108
109 pub fn to_map(properties: Option<Vec<GraphQLPropertyInstance>>) -> HashMap<String, Value> {
110 match properties {
111 Some(properties) => {
112 let mut props = HashMap::new();
113 for property in properties {
114 props.insert(property.name.clone(), property.value.clone());
115 }
116 props
117 }
118 None => HashMap::new(),
119 }
120 }
121
122 pub fn to_map_with_defaults(properties: Option<Vec<GraphQLPropertyInstance>>, property_types: PropertyTypes) -> HashMap<String, Value> {
123 let mut props = HashMap::new();
124 for property_type in property_types.iter() {
125 props.insert(property_type.name.clone(), property_type.data_type.default_value());
126 }
127 if let Some(properties) = properties {
128 for property in properties {
129 props.insert(property.name.clone(), property.value.clone());
130 }
131 }
132 props
133 }
134
135 pub fn to_property_instances_with_defaults(properties: Option<Vec<GraphQLPropertyInstance>>, property_types: PropertyTypes) -> PropertyInstances {
136 let property_instances = PropertyInstances::new();
137 for property_type in property_types.iter() {
138 property_instances.insert(property_type.name.clone(), property_type.data_type.default_value());
139 }
140 if let Some(properties) = properties {
141 for property in properties {
142 property_instances.insert(property.name.clone(), property.value.clone());
143 }
144 }
145 property_instances
146 }
147}