1use std::cmp::Ordering;
2use std::fmt::Display;
3use std::fmt::Formatter;
4use std::hash::Hash;
5use std::hash::Hasher;
6use std::ops::Deref;
7use std::ops::DerefMut;
8
9use const_format::formatcp;
10use dashmap::DashMap;
11use dashmap::iter::OwningIter;
12#[cfg(any(test, feature = "test"))]
13use default_test::DefaultTest;
14#[cfg(any(test, feature = "test"))]
15use rand::Rng;
16use schemars::JsonSchema;
17use schemars::Schema;
18use schemars::SchemaGenerator;
19use schemars::json_schema;
20use serde::Deserialize;
21use serde::Deserializer;
22use serde::Serialize;
23use serde::Serializer;
24use serde_json::Map;
25use serde_json::Value;
26use std::borrow::Cow;
27use typed_builder::TypedBuilder;
28use uuid::Uuid;
29
30use crate::AddExtensionError;
31use crate::ComponentTypeId;
32use crate::ComponentTypeIdContainer;
33use crate::ComponentTypeIds;
34#[cfg(any(test, feature = "test"))]
35use crate::EntityType;
36use crate::EntityTypeId;
37use crate::EntityTypeIds;
38use crate::Extension;
39use crate::ExtensionContainer;
40use crate::ExtensionTypeId;
41use crate::Extensions;
42use crate::JSON_SCHEMA_ID_URI_PREFIX;
43use crate::MutablePropertyInstanceSetter;
44use crate::NamespacedTypeGetter;
45use crate::PropertyInstanceGetter;
46use crate::PropertyInstances;
47use crate::RemoveExtensionError;
48use crate::TYPE_ID_TYPE_SEPARATOR;
49use crate::TypeDefinition;
50use crate::TypeDefinitionGetter;
51use crate::UpdateExtensionError;
52use crate::instances::named::NamedInstanceContainer;
53#[cfg(any(test, feature = "test"))]
54use crate::test_utils::default_from::DefaultFrom;
55#[cfg(any(test, feature = "test"))]
56use reactive_graph_utils_test::r_string;
57
58pub const JSON_SCHEMA_ID_ENTITY_INSTANCE: &str = formatcp!("{}/entity-instance.schema.json", JSON_SCHEMA_ID_URI_PREFIX);
59
60#[derive(Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize, JsonSchema, TypedBuilder)]
67#[serde(tag = "$id", rename = "https://schema.reactive-graph.io/schema/json/entity-instance.schema.json")]
68#[schemars(
69 title = "EntityInstance",
70 rename = "EntityInstance",
71 deny_unknown_fields,
72 extend("$id" = JSON_SCHEMA_ID_ENTITY_INSTANCE),
73 transform = add_json_schema_id_property
74)]
75pub struct EntityInstance {
76 #[serde(flatten)]
78 #[builder(setter(into))]
79 pub ty: EntityTypeId,
80
81 #[builder(default=Uuid::new_v4())]
83 pub id: Uuid,
84
85 #[serde(default = "String::new")]
87 #[builder(default, setter(into))]
88 pub name: String,
89
90 #[serde(default = "String::new")]
92 #[builder(default, setter(into))]
93 pub description: String,
94
95 #[serde(default = "PropertyInstances::new")]
102 #[builder(default, setter(into))]
103 pub properties: PropertyInstances,
104
105 #[serde(default = "ComponentTypeIds::new")]
107 #[builder(default, setter(into))]
108 pub components: ComponentTypeIds,
109
110 #[serde(default = "Extensions::new")]
115 #[builder(default, setter(into))]
116 pub extensions: Extensions,
117}
118
119impl EntityInstance {
120 pub fn new<T: Into<EntityTypeId>, P: Into<PropertyInstances>>(ty: T, id: Uuid, properties: P) -> EntityInstance {
122 EntityInstance {
123 ty: ty.into(),
124 id,
125 name: String::new(),
126 description: String::new(),
127 properties: properties.into(),
128 components: ComponentTypeIds::new(),
129 extensions: Extensions::new(),
130 }
131 }
132
133 pub fn new_from_type<N: Into<String>, T: Into<String>, P: Into<PropertyInstances>>(namespace: N, type_name: T, id: Uuid, properties: P) -> EntityInstance {
135 EntityInstance {
136 ty: EntityTypeId::new_from_type(namespace.into(), type_name.into()),
137 id,
138 name: String::new(),
139 description: String::new(),
140 properties: properties.into(),
141 components: ComponentTypeIds::new(),
142 extensions: Extensions::new(),
143 }
144 }
145
146 pub fn new_without_properties<T: Into<EntityTypeId>>(ty: T, id: Uuid) -> EntityInstance {
148 EntityInstance {
149 ty: ty.into(),
150 id,
151 name: String::new(),
152 description: String::new(),
153 properties: PropertyInstances::new(),
154 components: ComponentTypeIds::new(),
155 extensions: Extensions::new(),
156 }
157 }
158}
159
160impl NamedInstanceContainer for EntityInstance {
161 fn name(&self) -> String {
162 self.name.clone()
163 }
164
165 fn description(&self) -> String {
166 self.description.clone()
167 }
168}
169
170impl PropertyInstanceGetter for EntityInstance {
171 fn get<S: Into<String>>(&self, property_name: S) -> Option<Value> {
172 self.properties.get(property_name.into())
173 }
174
175 fn as_bool<S: Into<String>>(&self, property_name: S) -> Option<bool> {
176 self.properties.as_bool(property_name.into())
177 }
178
179 fn as_u64<S: Into<String>>(&self, property_name: S) -> Option<u64> {
180 self.properties.as_u64(property_name.into())
181 }
182
183 fn as_i64<S: Into<String>>(&self, property_name: S) -> Option<i64> {
184 self.properties.as_i64(property_name.into())
185 }
186
187 fn as_f64<S: Into<String>>(&self, property_name: S) -> Option<f64> {
188 self.properties.as_f64(property_name.into())
189 }
190
191 fn as_string<S: Into<String>>(&self, property_name: S) -> Option<String> {
192 self.properties.as_string(property_name.into())
193 }
194
195 fn as_array<S: Into<String>>(&self, property_name: S) -> Option<Vec<Value>> {
196 self.properties.as_array(property_name.into())
197 }
198
199 fn as_object<S: Into<String>>(&self, property_name: S) -> Option<Map<String, Value>> {
200 self.properties.as_object(property_name.into())
201 }
202}
203
204impl MutablePropertyInstanceSetter for EntityInstance {
205 fn set<S: Into<String>>(&mut self, property_name: S, value: Value) {
206 self.properties.set(property_name.into(), value);
207 }
208}
209
210impl ComponentTypeIdContainer for EntityInstance {
211 fn is_a(&self, ty: &ComponentTypeId) -> bool {
212 self.components.is_a(ty)
213 }
214
215 fn add_component<C: Into<ComponentTypeId>>(&self, ty: C) -> bool {
216 self.components.add_component(ty)
217 }
218
219 fn add_components<C: Into<ComponentTypeIds>>(&mut self, components_to_add: C) {
220 self.components.add_components(components_to_add)
221 }
222
223 fn remove_component(&self, ty: &ComponentTypeId) -> Option<ComponentTypeId> {
224 self.components.remove_component(ty)
225 }
226
227 fn remove_components<C: Into<ComponentTypeIds>>(&mut self, components_to_remove: C) {
228 self.components.remove_components(components_to_remove)
229 }
230}
231
232impl ExtensionContainer for EntityInstance {
233 fn has_own_extension(&self, ty: &ExtensionTypeId) -> bool {
234 self.extensions.has_own_extension(ty)
235 }
236
237 fn get_own_extension(&self, ty: &ExtensionTypeId) -> Option<Extension> {
238 self.extensions.get_own_extension(ty)
239 }
240
241 fn add_extension<E: Into<Extension>>(&self, extension: E) -> Result<ExtensionTypeId, AddExtensionError> {
242 self.extensions.add_extension(extension)
243 }
244
245 fn update_extension<T: Into<ExtensionTypeId>, E: Into<Extension>>(&self, ty: T, extension: E) -> Result<Extension, UpdateExtensionError> {
246 self.extensions.update_extension(ty, extension)
247 }
248
249 fn remove_extension<T: Into<ExtensionTypeId>>(&self, ty: T) -> Result<Extension, RemoveExtensionError> {
250 self.extensions.remove_extension(ty)
251 }
252
253 fn merge_extensions<E: Into<Extensions>>(&mut self, extensions_to_merge: E) {
254 self.extensions.merge_extensions(extensions_to_merge)
255 }
256}
257
258impl NamespacedTypeGetter for EntityInstance {
259 fn namespace(&self) -> String {
260 self.ty.namespace()
261 }
262
263 fn type_name(&self) -> String {
264 self.ty.type_name()
265 }
266}
267
268impl TypeDefinitionGetter for EntityInstance {
269 fn type_definition(&self) -> TypeDefinition {
270 self.ty.type_definition()
271 }
272}
273
274impl PartialEq<Uuid> for EntityInstance {
275 fn eq(&self, id: &Uuid) -> bool {
276 self.id == *id
277 }
278}
279
280impl PartialOrd<Self> for EntityInstance {
281 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
282 Some(self.cmp(other))
283 }
284}
285
286impl Ord for EntityInstance {
287 fn cmp(&self, other: &Self) -> Ordering {
288 self.id.cmp(&other.id)
289 }
290}
291
292impl Display for EntityInstance {
293 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
294 write!(f, "{}{}{}", &self.ty, TYPE_ID_TYPE_SEPARATOR, self.id)
295 }
296}
297
298#[derive(Clone, Debug, Default)]
299pub struct EntityInstances(DashMap<Uuid, EntityInstance>);
300
301impl EntityInstances {
302 pub fn new() -> Self {
303 EntityInstances(DashMap::new())
304 }
305
306 pub fn new_with_instance<E: Into<EntityInstance>>(entity_instance: E) -> Self {
307 let entity_instances = EntityInstances::new();
308 entity_instances.push(entity_instance.into());
309 entity_instances
310 }
311
312 pub fn push<E: Into<EntityInstance>>(&self, entity_instance: E) {
313 let entity_instance = entity_instance.into();
314 self.0.insert(entity_instance.id, entity_instance);
315 }
316
317 pub fn to_vec(&self) -> Vec<EntityInstance> {
318 let mut items: Vec<_> = self.iter().map(|item| item.value().clone()).collect();
319 items.sort();
320 items
321 }
322
323 pub fn get_type_ids(&self) -> EntityTypeIds {
325 self.iter().map(|entity_instance| entity_instance.ty.clone()).collect()
326 }
327}
328
329impl Deref for EntityInstances {
330 type Target = DashMap<Uuid, EntityInstance>;
331
332 fn deref(&self) -> &Self::Target {
333 &self.0
334 }
335}
336
337impl DerefMut for EntityInstances {
338 fn deref_mut(&mut self) -> &mut Self::Target {
339 &mut self.0
340 }
341}
342
343impl IntoIterator for EntityInstances {
344 type Item = (Uuid, EntityInstance);
345 type IntoIter = OwningIter<Uuid, EntityInstance>;
346
347 fn into_iter(self) -> Self::IntoIter {
348 self.0.into_iter()
349 }
350}
351
352impl PartialEq for EntityInstances {
353 fn eq(&self, other: &Self) -> bool {
354 self.0.iter().all(|self_entity_instance| other.contains_key(&self_entity_instance.id))
355 && other.iter().all(|other_entity_instance| self.contains_key(&other_entity_instance.id))
356 }
357}
358
359impl Eq for EntityInstances {}
360
361impl Hash for EntityInstances {
362 fn hash<H: Hasher>(&self, state: &mut H) {
363 self.to_vec().hash(state);
364 }
365}
366
367impl Serialize for EntityInstances {
368 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
369 where
370 S: Serializer,
371 {
372 serializer.collect_seq(self.iter())
373 }
374}
375
376impl<'de> Deserialize<'de> for EntityInstances {
377 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
378 where
379 D: Deserializer<'de>,
380 {
381 Ok(Vec::<EntityInstance>::deserialize(deserializer)?.into())
382 }
383}
384
385impl JsonSchema for EntityInstances {
386 fn schema_name() -> Cow<'static, str> {
387 "EntityInstances".into()
388 }
389
390 fn json_schema(schema_generator: &mut SchemaGenerator) -> Schema {
391 let sub_schema: Schema = schema_generator.subschema_for::<EntityInstance>();
392 json_schema!({
393 "type": "array",
394 "items": sub_schema,
395 "description": "Entity Instances",
396 })
397 }
398}
399
400impl From<Vec<EntityInstance>> for EntityInstances {
401 fn from(entity_instances: Vec<EntityInstance>) -> Self {
402 Self(
403 entity_instances
404 .into_iter()
405 .map(|entity_instance| (entity_instance.id, entity_instance))
406 .collect(),
407 )
408 }
409}
410
411impl From<EntityInstances> for Vec<EntityInstance> {
412 fn from(entity_instances: EntityInstances) -> Self {
413 entity_instances.to_vec()
414 }
415}
416
417impl From<&EntityInstances> for Vec<EntityInstance> {
418 fn from(entity_instances: &EntityInstances) -> Self {
419 entity_instances.0.iter().map(|entity_instance| entity_instance.clone()).collect()
420 }
421}
422
423impl From<DashMap<Uuid, EntityInstance>> for EntityInstances {
424 fn from(entity_instances: DashMap<Uuid, EntityInstance>) -> Self {
425 Self(entity_instances)
426 }
427}
428
429impl From<&DashMap<Uuid, EntityInstance>> for EntityInstances {
430 fn from(entity_instances: &DashMap<Uuid, EntityInstance>) -> Self {
431 Self(entity_instances.clone())
432 }
433}
434
435impl From<EntityInstances> for DashMap<Uuid, EntityInstance> {
436 fn from(entity_instances: EntityInstances) -> Self {
437 entity_instances.0
438 }
439}
440
441impl FromIterator<EntityInstance> for EntityInstances {
442 fn from_iter<I: IntoIterator<Item = EntityInstance>>(iter: I) -> Self {
443 let entity_instances = Self::new();
444 for entity_instance in iter {
445 entity_instances.insert(entity_instance.id, entity_instance);
446 }
447 entity_instances
448 }
449}
450
451#[cfg(any(test, feature = "test"))]
452impl DefaultTest for EntityInstance {
453 fn default_test() -> Self {
454 EntityInstance::builder()
455 .ty(EntityTypeId::default_test())
456 .name(r_string())
457 .description(r_string())
458 .properties(PropertyInstances::default_test())
459 .extensions(Extensions::default_test())
460 .build()
461 }
462}
463
464#[cfg(any(test, feature = "test"))]
465impl DefaultFrom<EntityType> for EntityInstance {
466 fn default_from(entity_type: &EntityType) -> Self {
467 let properties = PropertyInstances::default_from(&entity_type.properties);
468 EntityInstance::builder()
469 .ty(&entity_type.ty)
470 .name(r_string())
471 .description(&entity_type.description)
472 .properties(properties)
473 .extensions(Extensions::default_test())
474 .build()
475 }
476}
477
478#[cfg(any(test, feature = "test"))]
479impl DefaultTest for EntityInstances {
480 fn default_test() -> Self {
481 let entity_instances = EntityInstances::new();
482 let mut rng = rand::rng();
483 for _ in 0..rng.random_range(0..10) {
484 entity_instances.push(EntityInstance::default_test());
485 }
486 entity_instances
487 }
488}
489
490fn add_json_schema_id_property(schema: &mut Schema) {
491 crate::json_schema::add_json_schema_id_property(schema, JSON_SCHEMA_ID_ENTITY_INSTANCE);
492}
493
494#[cfg(test)]
495pub mod entity_instance_tests {
496 use std::ops::Index;
497
498 use default_test::DefaultTest;
499 use schemars::schema_for;
500 use serde_json::json;
501 use uuid::Uuid;
502
503 use crate::ComponentTypeId;
504 use crate::ComponentTypeIdContainer;
505 use crate::ComponentTypeIds;
506 use crate::EntityInstance;
507 use crate::EntityTypeId;
508 use crate::Extension;
509 use crate::ExtensionContainer;
510 use crate::ExtensionTypeId;
511 use crate::Extensions;
512 use crate::MutablePropertyInstanceSetter;
513 use crate::NamespacedTypeGetter;
514 use crate::PropertyInstanceGetter;
515 use crate::PropertyInstances;
516 use reactive_graph_utils_test::r_string;
517
518 pub fn create_entity_instance_with_property<S: Into<String>>(property_name: S) -> EntityInstance {
519 let properties = PropertyInstances::new().property(property_name, json!(r_string()));
520 EntityInstance::builder()
522 .ty(EntityTypeId::default_test())
523 .name(r_string())
524 .description(r_string())
525 .properties(properties)
526 .extensions(Extensions::default_test())
527 .build()
528 }
529
530 pub fn create_entity_instance_from_type<N: Into<String>, T: Into<String>>(namespace: N, type_name: T) -> EntityInstance {
531 EntityInstance::builder()
532 .ty(EntityTypeId::new_from_type(namespace.into(), type_name.into()))
533 .build()
534 }
535
536 #[test]
537 fn entity_instance_test() {
538 let uuid = Uuid::new_v4();
539 let namespace = r_string();
540 let type_name = r_string();
541 let name = r_string();
542 let description = r_string();
543 let property_name = r_string();
544 let property_value = json!(r_string());
545 let properties = PropertyInstances::new().property(&property_name, property_value.clone());
546
547 let component_namespace = r_string();
548 let component_name = r_string();
549 let component_ty = ComponentTypeId::new_from_type(&component_namespace, &component_name);
550 let components = ComponentTypeIds::new().component(component_ty.clone());
551
552 let extension_namespace = r_string();
553 let extension_name = r_string();
554 let extension_ty = ExtensionTypeId::new_from_type(&extension_namespace, &extension_name);
555 let extension_value = json!("extension_value");
556 let extension = Extension {
557 ty: extension_ty.clone(),
558 description: r_string(),
559 extension: extension_value.clone(),
560 };
561
562 let other_extension_ty = ExtensionTypeId::new_from_type(&extension_namespace, &r_string());
563 let other_extension = Extension::new(&other_extension_ty, r_string(), extension_value.clone());
564
565 let extensions = Extensions::new().extension(extension.clone()).extension(other_extension.clone());
566 let ty = EntityTypeId::new_from_type(namespace.clone(), type_name.clone());
570 let entity_instance = EntityInstance {
571 ty: ty.clone(),
572 id: uuid.clone(),
573 name: name.to_string(),
574 description: description.to_string(),
575 properties: properties.clone(),
576 components: components.clone(),
577 extensions: extensions.clone(),
578 };
579 assert_eq!(namespace, entity_instance.namespace());
580 assert_eq!(type_name, entity_instance.type_name());
581 assert_eq!(uuid.clone(), entity_instance.id.clone());
582 assert_eq!(name.clone(), entity_instance.name.clone());
583 assert_eq!(description.clone(), entity_instance.description.clone());
584 assert_eq!(properties.clone(), entity_instance.properties.clone());
585 assert!(entity_instance.get(property_name.clone()).is_some());
586 assert!(entity_instance.get(r_string()).is_none());
587 assert_eq!(property_value.clone(), entity_instance.get(property_name.clone()).unwrap());
588 assert!(entity_instance.components.contains(&component_ty.clone()));
589 assert!(entity_instance.components.is_a(&component_ty));
590 assert!(entity_instance.is_a(&component_ty));
591 assert!(!entity_instance.is_a(&ComponentTypeId::generate_random()));
592 assert!(entity_instance.extensions.has_own_extension(&extension_ty));
593 assert!(entity_instance.has_own_extension(&extension_ty));
594 let non_existing_extension = ExtensionTypeId::new_from_type(r_string(), r_string());
595 assert!(!entity_instance.has_own_extension(&non_existing_extension));
596 assert_eq!(extension.extension, entity_instance.get_own_extension(&extension_ty).unwrap().extension);
597 assert_eq!(format!("{}__{}", entity_instance.ty, entity_instance.id), format!("{}", entity_instance));
598 }
599
600 #[test]
601 fn create_entity_instance_test() {
602 let uuid = Uuid::new_v4();
603 let namespace = r_string();
604 let type_name = r_string();
605 let property_name = r_string();
606 let property_value = json!(r_string());
607 let properties = PropertyInstances::new().property(&property_name, property_value.clone());
608 let ty = EntityTypeId::new_from_type(namespace.clone(), type_name.clone());
609 let entity_instance = EntityInstance::new(ty, uuid, properties.clone());
610 assert_eq!(namespace, entity_instance.namespace());
611 assert_eq!(type_name, entity_instance.type_name());
612 assert_eq!(uuid, entity_instance.id.clone());
613 assert_eq!(properties.clone(), properties.clone());
614 assert!(entity_instance.get(property_name.clone()).is_some());
615 assert!(entity_instance.get(r_string()).is_none());
616 assert_eq!(property_value.clone(), entity_instance.get(property_name.clone()).unwrap());
617 }
618
619 #[test]
620 fn create_entity_instance_without_properties_test() {
621 let uuid = Uuid::new_v4();
622 let namespace = r_string();
623 let type_name = r_string();
624 let ty = EntityTypeId::new_from_type(namespace.clone(), type_name.clone());
625 let entity_instance = EntityInstance::new_without_properties(ty, uuid);
626 assert_eq!(namespace, entity_instance.namespace());
627 assert_eq!(type_name, entity_instance.type_name());
628 assert_eq!(uuid, entity_instance.id.clone());
629 assert!(entity_instance.get(r_string()).is_none());
630 }
631
632 #[test]
633 fn entity_instance_typed_getter_test() {
634 let uuid = Uuid::new_v4();
635 let namespace = r_string();
636 let type_name = r_string();
637 let property_name = r_string();
638 let properties = PropertyInstances::new().property(&property_name, json!(false));
639 let ty = EntityTypeId::new_from_type(namespace.clone(), type_name.clone());
640 let mut i = EntityInstance::new(ty, uuid, properties);
641 i.set(property_name.clone(), json!(true));
642 assert!(i.as_bool(property_name.clone()).unwrap());
643 i.set(property_name.clone(), json!(false));
644 assert!(!i.as_bool(property_name.clone()).unwrap());
645 i.set(property_name.clone(), json!(123));
646 assert_eq!(123, i.as_u64(property_name.clone()).unwrap());
647 i.set(property_name.clone(), json!(-123));
648 assert_eq!(-123, i.as_i64(property_name.clone()).unwrap());
649 i.set(property_name.clone(), json!(1.23));
650 assert_eq!(1.23, i.as_f64(property_name.clone()).unwrap());
651 let s = r_string();
652 i.set(property_name.clone(), json!(s.clone()));
653 assert_eq!(s, i.as_string(property_name.clone()).unwrap());
654 let a = json!([1, 2, 3]);
655 i.set(property_name.clone(), a.clone());
656 assert_eq!(json!(1), i.as_array(property_name.clone()).unwrap().index(0).clone());
657 assert_eq!(json!(2), i.as_array(property_name.clone()).unwrap().index(1).clone());
658 assert_eq!(json!(3), i.as_array(property_name.clone()).unwrap().index(2).clone());
659 let o = json!({
660 "k": "v"
661 });
662 i.set(property_name.clone(), o.clone());
663 assert_eq!(json!("v"), i.as_object(property_name.clone()).unwrap().index("k").clone());
664 }
665
666 #[test]
667 fn entity_instance_ser_test() {
668 let uuid = Uuid::new_v4();
669 let namespace = r_string();
670 let type_name = r_string();
671 let name = r_string();
672 let description = r_string();
673 let property_name = r_string();
674 let property_value = json!(r_string());
675 let properties = PropertyInstances::new().property(&property_name, property_value.clone());
676
677 let extension_namespace = r_string();
678 let extension_name = r_string();
679 let extension_ty = ExtensionTypeId::new_from_type(&extension_namespace, &extension_name);
680 let extension_value = json!("extension_value");
681 let extension = Extension {
682 ty: extension_ty.clone(),
683 description: r_string(),
684 extension: extension_value.clone(),
685 };
686 let other_extension_ty = ExtensionTypeId::new_from_type(&extension_namespace, &r_string());
687 let other_extension = Extension::new(&other_extension_ty, r_string(), extension_value.clone());
688 let extensions = Extensions::new().extension(extension.clone()).extension(other_extension.clone());
689 let component_namespace = r_string();
690 let component_name = r_string();
691 let component_ty = ComponentTypeId::new_from_type(&component_namespace, &component_name);
692 let components = ComponentTypeIds::new().component(component_ty.clone());
693
694 let ty = EntityTypeId::new_from_type(namespace.clone(), type_name.clone());
695 let entity_instance = EntityInstance {
696 ty: ty.clone(),
697 id: uuid.clone(),
698 name: name.to_string(),
699 description: description.to_string(),
700 properties: properties.clone(),
701 components: components.clone(),
702 extensions: extensions.clone(),
703 };
704 println!("{}", serde_json::to_string_pretty(&entity_instance).expect("Failed to serialize entity instance"));
705 }
706
707 #[test]
708 fn entity_instance_de_test() {
709 let s = r#"{
710 "namespace": "XARPbZkHrU",
711 "type_name": "zHMZhLUpeH",
712 "id": "590f4446-b080-48d3-bd14-05e09de89e62",
713 "name": "PRAwNv1I",
714 "description": "gDyZTYONjh",
715 "properties": {
716 "NaUPOBoqyp": "qEnGqwNeEL"
717 },
718 "components": [
719 {
720 "namespace": "c_namespace",
721 "type_name": "c_name"
722 }
723 ],
724 "extensions": [
725 {
726 "namespace": "ext_namespace",
727 "type_name": "ext_name",
728 "extension": "extension_value"
729 },
730 {
731 "namespace": "other_ext_namespace",
732 "type_name": "other_ext_name",
733 "extension": "other_extension_value"
734 }
735 ]
736}"#;
737 let entity_instance: EntityInstance = serde_json::from_str(s).unwrap();
738 assert_eq!("XARPbZkHrU", entity_instance.namespace());
739 assert_eq!("zHMZhLUpeH", entity_instance.type_name());
740 assert_eq!("e__XARPbZkHrU__zHMZhLUpeH", entity_instance.ty.to_string());
741 assert_eq!("PRAwNv1I", entity_instance.name);
742 assert_eq!("gDyZTYONjh", entity_instance.description);
743 assert_eq!(1, entity_instance.properties.len());
744 let property = entity_instance.properties.get("NaUPOBoqyp").expect("Missing property");
745 assert_eq!("qEnGqwNeEL", property.as_str().unwrap());
746 assert_eq!(1, entity_instance.components.len());
747 assert!(entity_instance.components.contains(&ComponentTypeId::new_from_type("c_namespace", "c_name")));
748 assert!(entity_instance.components.is_a(&ComponentTypeId::new_from_type("c_namespace", "c_name")));
749 assert!(entity_instance.is_a(&ComponentTypeId::new_from_type("c_namespace", "c_name")));
750 assert_eq!(2, entity_instance.extensions.len());
751 assert!(
752 entity_instance
753 .extensions
754 .has_own_extension(&ExtensionTypeId::new_from_type("ext_namespace", "ext_name"))
755 );
756 assert_eq!(
757 json!("extension_value"),
758 entity_instance
759 .extensions
760 .get_own_extension(&ExtensionTypeId::new_from_type("ext_namespace", "ext_name"))
761 .unwrap()
762 .extension
763 );
764 assert!(
765 entity_instance
766 .extensions
767 .has_own_extension(&ExtensionTypeId::new_from_type("other_ext_namespace", "other_ext_name"))
768 );
769 assert_eq!(
770 json!("other_extension_value"),
771 entity_instance
772 .extensions
773 .get_own_extension(&ExtensionTypeId::new_from_type("other_ext_namespace", "other_ext_name"))
774 .unwrap()
775 .extension
776 );
777 }
778
779 #[test]
780 fn entity_instance_json_schema() {
781 let schema = schema_for!(EntityInstance);
782 println!("{}", serde_json::to_string_pretty(&schema).unwrap());
783 }
784}