reactive_graph_graph/instances/flows/
flow_instance.rs1use crate::EntityInstance;
2use crate::EntityInstances;
3#[cfg(any(test, feature = "test"))]
4use crate::EntityType;
5use crate::EntityTypeId;
6use crate::JSON_SCHEMA_ID_URI_PREFIX;
7use crate::NamespacedTypeGetter;
8use crate::RelationInstances;
9use crate::TYPE_ID_TYPE_SEPARATOR;
10use crate::TypeDefinition;
11use crate::TypeDefinitionGetter;
12use crate::instances::named::NamedInstanceContainer;
13use const_format::formatcp;
14use dashmap::DashMap;
15use dashmap::iter::OwningIter;
16#[cfg(any(test, feature = "test"))]
17use default_test::DefaultTest;
18#[cfg(any(test, feature = "test"))]
19use rand::Rng;
20#[cfg(any(test, feature = "test"))]
21use reactive_graph_utils_test::DefaultFrom;
22use schemars::JsonSchema;
23use schemars::Schema;
24use schemars::SchemaGenerator;
25use schemars::json_schema;
26use serde::Deserialize;
27use serde::Deserializer;
28use serde::Serialize;
29use serde::Serializer;
30use std::borrow::Cow;
31use std::cmp::Ordering;
32use std::fmt::Display;
33use std::fmt::Formatter;
34use std::hash::Hash;
35use std::hash::Hasher;
36use std::ops::Deref;
37use std::ops::DerefMut;
38use typed_builder::TypedBuilder;
39use uuid::Uuid;
40
41pub const JSON_SCHEMA_ID_FLOW_INSTANCE: &str = formatcp!("{}/flow-instance.schema.json", JSON_SCHEMA_ID_URI_PREFIX);
42
43#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, TypedBuilder)]
58#[serde(tag = "$id", rename = "https://schema.reactive-graph.io/schema/json/flow-instance.schema.json")]
59#[schemars(
60 title = "FlowInstance",
61 deny_unknown_fields,
62 extend("$id" = JSON_SCHEMA_ID_FLOW_INSTANCE),
63 transform = add_json_schema_id_property
64)]
65pub struct FlowInstance {
66 pub id: Uuid,
71
72 #[serde(flatten)]
74 #[builder(setter(into))]
75 pub ty: EntityTypeId,
76
77 #[serde(default = "String::new")]
79 #[builder(default, setter(into))]
80 pub name: String,
81
82 #[serde(default = "String::new")]
84 #[builder(default, setter(into))]
85 pub description: String,
86
87 #[serde(default = "EntityInstances::new", alias = "entities")]
92 #[builder(default, setter(into))]
93 pub entity_instances: EntityInstances,
94
95 #[serde(default = "RelationInstances::new", alias = "relations")]
99 #[builder(default, setter(into))]
100 pub relation_instances: RelationInstances,
101}
102
103impl FlowInstance {
104 pub fn from_instance_with_name<S: Into<String>>(wrapper_entity_instance: EntityInstance, name: S) -> FlowInstance {
106 FlowInstance {
107 id: wrapper_entity_instance.id,
108 ty: wrapper_entity_instance.ty.clone(),
109 name: name.into(),
110 description: String::new(),
111 entity_instances: EntityInstances::new_with_instance(wrapper_entity_instance),
112 relation_instances: RelationInstances::new(),
113 }
114 }
115}
116
117impl NamedInstanceContainer for FlowInstance {
118 fn name(&self) -> String {
119 self.name.clone()
120 }
121
122 fn description(&self) -> String {
123 self.description.clone()
124 }
125}
126
127impl From<EntityInstance> for FlowInstance {
128 fn from(wrapper_entity_instance: EntityInstance) -> FlowInstance {
129 FlowInstance {
130 id: wrapper_entity_instance.id,
131 ty: wrapper_entity_instance.ty.clone(),
132 name: String::new(),
133 description: String::new(),
134 entity_instances: EntityInstances::new_with_instance(wrapper_entity_instance),
135 relation_instances: RelationInstances::new(),
136 }
137 }
138}
139
140impl NamespacedTypeGetter for FlowInstance {
141 fn namespace(&self) -> String {
142 self.ty.namespace()
143 }
144
145 fn type_name(&self) -> String {
146 self.ty.type_name()
147 }
148}
149
150impl TypeDefinitionGetter for FlowInstance {
151 fn type_definition(&self) -> TypeDefinition {
152 self.ty.type_definition()
153 }
154}
155impl PartialEq<Uuid> for FlowInstance {
156 fn eq(&self, id: &Uuid) -> bool {
157 self.id == *id
158 }
159}
160
161impl PartialOrd<Self> for FlowInstance {
162 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
163 Some(self.cmp(other))
164 }
165}
166
167impl Ord for FlowInstance {
168 fn cmp(&self, other: &Self) -> Ordering {
169 self.id.cmp(&other.id)
170 }
171}
172
173impl Display for FlowInstance {
174 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
175 write!(f, "{}{}{}", &self.ty, TYPE_ID_TYPE_SEPARATOR, self.id)
176 }
177}
178
179#[derive(Clone, Debug, Default)]
180pub struct FlowInstances(DashMap<Uuid, FlowInstance>);
181
182impl FlowInstances {
183 pub fn new() -> Self {
184 FlowInstances(DashMap::new())
185 }
186
187 pub fn new_with_instance<E: Into<FlowInstance>>(flow_instance: E) -> Self {
188 let flow_instances = FlowInstances::new();
189 flow_instances.push(flow_instance.into());
190 flow_instances
191 }
192
193 pub fn push<E: Into<FlowInstance>>(&self, flow_instance: E) {
194 let flow_instance = flow_instance.into();
195 self.0.insert(flow_instance.id, flow_instance);
196 }
197
198 pub fn to_vec(&self) -> Vec<FlowInstance> {
199 let mut items: Vec<_> = self.iter().map(|item| item.value().clone()).collect();
200 items.sort();
201 items
202 }
203
204 }
209
210impl Deref for FlowInstances {
211 type Target = DashMap<Uuid, FlowInstance>;
212
213 fn deref(&self) -> &Self::Target {
214 &self.0
215 }
216}
217
218impl DerefMut for FlowInstances {
219 fn deref_mut(&mut self) -> &mut Self::Target {
220 &mut self.0
221 }
222}
223
224impl IntoIterator for FlowInstances {
225 type Item = (Uuid, FlowInstance);
226 type IntoIter = OwningIter<Uuid, FlowInstance>;
227
228 fn into_iter(self) -> Self::IntoIter {
229 self.0.into_iter()
230 }
231}
232
233impl PartialEq for FlowInstances {
234 fn eq(&self, other: &Self) -> bool {
235 self.0.iter().all(|self_flow_instance| other.contains_key(&self_flow_instance.id))
236 && other.iter().all(|other_flow_instance| self.contains_key(&other_flow_instance.id))
237 }
238}
239
240impl Eq for FlowInstances {}
241
242impl Hash for FlowInstances {
243 fn hash<H: Hasher>(&self, state: &mut H) {
244 self.to_vec().hash(state);
245 }
246}
247
248impl Serialize for FlowInstances {
249 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
250 where
251 S: Serializer,
252 {
253 serializer.collect_seq(self.iter())
254 }
255}
256
257impl<'de> Deserialize<'de> for FlowInstances {
258 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
259 where
260 D: Deserializer<'de>,
261 {
262 Ok(Vec::<FlowInstance>::deserialize(deserializer)?.into())
263 }
264}
265
266impl JsonSchema for FlowInstances {
267 fn schema_name() -> Cow<'static, str> {
268 "FlowInstances".into()
269 }
270
271 fn json_schema(schema_generator: &mut SchemaGenerator) -> Schema {
272 let sub_schema: Schema = schema_generator.subschema_for::<FlowInstance>();
273 json_schema!({
274 "type": "array",
275 "items": sub_schema,
276 "description": "Flow Instances",
277 })
278 }
279}
280
281impl From<Vec<FlowInstance>> for FlowInstances {
282 fn from(flow_instances: Vec<FlowInstance>) -> Self {
283 Self(flow_instances.into_iter().map(|flow_instance| (flow_instance.id, flow_instance)).collect())
284 }
285}
286
287impl From<FlowInstances> for Vec<FlowInstance> {
288 fn from(flow_instances: FlowInstances) -> Self {
289 flow_instances.to_vec()
290 }
291}
292
293impl From<&FlowInstances> for Vec<FlowInstance> {
294 fn from(flow_instances: &FlowInstances) -> Self {
295 flow_instances.0.iter().map(|flow_instance| flow_instance.clone()).collect()
296 }
297}
298
299impl From<DashMap<Uuid, FlowInstance>> for FlowInstances {
300 fn from(flow_instances: DashMap<Uuid, FlowInstance>) -> Self {
301 Self(flow_instances)
302 }
303}
304
305impl From<&DashMap<Uuid, FlowInstance>> for FlowInstances {
306 fn from(flow_instances: &DashMap<Uuid, FlowInstance>) -> Self {
307 Self(flow_instances.clone())
308 }
309}
310
311impl From<FlowInstances> for DashMap<Uuid, FlowInstance> {
312 fn from(flow_instances: FlowInstances) -> Self {
313 flow_instances.0
314 }
315}
316
317impl FromIterator<FlowInstance> for FlowInstances {
318 fn from_iter<I: IntoIterator<Item = FlowInstance>>(iter: I) -> Self {
319 let flow_instances = Self::new();
320 for flow_instance in iter {
321 flow_instances.insert(flow_instance.id, flow_instance);
322 }
323 flow_instances
324 }
325}
326
327#[cfg(any(test, feature = "test"))]
328impl DefaultTest for FlowInstance {
329 fn default_test() -> Self {
330 let entity_type = EntityType::default_test();
331 let wrapper_entity_instance = EntityInstance::default_from(&entity_type);
332 let id = wrapper_entity_instance.id;
333
334 let entity_instances = EntityInstances::default_test();
335 entity_instances.push(wrapper_entity_instance);
336
337 FlowInstance::builder()
338 .ty(entity_type.ty.clone())
339 .id(id)
340 .entity_instances(entity_instances)
341 .build()
342 }
343}
344
345#[cfg(any(test, feature = "test"))]
346impl DefaultFrom<EntityType> for FlowInstance {
347 fn default_from(entity_type: &EntityType) -> Self {
348 Self::default_from(&EntityInstance::default_from(entity_type))
349 }
350}
351
352#[cfg(any(test, feature = "test"))]
353impl DefaultFrom<EntityInstance> for FlowInstance {
354 fn default_from(wrapper_entity_instance: &EntityInstance) -> Self {
355 FlowInstance::from(wrapper_entity_instance.clone())
356 }
357}
358
359#[cfg(any(test, feature = "test"))]
360impl DefaultTest for FlowInstances {
361 fn default_test() -> Self {
362 let flow_instances = FlowInstances::new();
363 let mut rng = rand::rng();
364 for _ in 0..rng.random_range(0..10) {
365 flow_instances.push(FlowInstance::default_test());
366 }
367 flow_instances
368 }
369}
370
371fn add_json_schema_id_property(schema: &mut Schema) {
372 crate::json_schema::add_json_schema_id_property(schema, JSON_SCHEMA_ID_FLOW_INSTANCE);
373}