reactive_graph_graph/instances/entities/
entity_instance.rs

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/// Entity instances represents an typed object which contains properties.
61///
62/// The entity type defines the properties (name, data type and socket type).
63///
64/// In contrast to the entity type the entity instance stores values in its
65/// properties.
66#[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    /// The type definition of the entity type.
77    #[serde(flatten)]
78    #[builder(setter(into))]
79    pub ty: EntityTypeId,
80
81    /// The unique identifier of the entity instance.
82    #[builder(default=Uuid::new_v4())]
83    pub id: Uuid,
84
85    /// The name of the entity instance.
86    #[serde(default = "String::new")]
87    #[builder(default, setter(into))]
88    pub name: String,
89
90    /// The description of the entity instance.
91    #[serde(default = "String::new")]
92    #[builder(default, setter(into))]
93    pub description: String,
94
95    /// The properties of the entity instance.
96    ///
97    /// Each property is represented by its name (String) and it's value. The value is
98    /// a representation of a JSON. Therefore, the value can be boolean, number, string,
99    /// array or an object. For more information about the data types please look at
100    /// <https://docs.serde.rs/serde_json/value/enum.Value.html>
101    #[serde(default = "PropertyInstances::new")]
102    #[builder(default, setter(into))]
103    pub properties: PropertyInstances,
104
105    /// The components of the entity instance.
106    #[serde(default = "ComponentTypeIds::new")]
107    #[builder(default, setter(into))]
108    pub components: ComponentTypeIds,
109
110    //
111    // TODO: behaviours?
112    //
113    /// Entity instance specific extensions.
114    #[serde(default = "Extensions::new")]
115    #[builder(default, setter(into))]
116    pub extensions: Extensions,
117}
118
119impl EntityInstance {
120    /// Constructs a new entity instance with the given type.
121    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    /// Constructs a new entity instance with the given namespace, type_name, id and properties.
134    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    /// Constructs a new entity instance with the given type and id but without properties.
147    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    // TODO: deduplicate?
324    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        // properties.insert(property_name.into(), json!(r_string()));
521        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        // extensions.push(extension.clone());
567        // extensions.push(other_extension);
568
569        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}