reactive_graph_reactive_service_impl/
reactive_entity_manager_impl.rs1use std::collections::HashMap;
2use std::sync::Arc;
3use std::sync::RwLock;
4use std::sync::atomic::AtomicBool;
5use std::sync::atomic::Ordering;
6
7use async_trait::async_trait;
8use dashmap::DashMap;
9use log::error;
10use path_tree::PathTree;
11use serde_json::Value;
12use springtime_di::Component;
13use springtime_di::component_alias;
14use tokio::time::sleep;
15use uuid::Uuid;
16
17use reactive_graph_behaviour_model_api::BehaviourTypeId;
18use reactive_graph_behaviour_model_api::BehaviourTypesContainer;
19use reactive_graph_behaviour_model_api::ComponentBehaviourTypeId;
20use reactive_graph_behaviour_model_api::EntityBehaviourTypeId;
21use reactive_graph_behaviour_service_api::EntityBehaviourManager;
22use reactive_graph_behaviour_service_api::EntityComponentBehaviourManager;
23use reactive_graph_graph::ComponentContainer;
24use reactive_graph_graph::ComponentTypeId;
25use reactive_graph_graph::EntityInstance;
26use reactive_graph_graph::EntityTypeId;
27use reactive_graph_graph::Mutability;
28use reactive_graph_graph::NamespacedTypeGetter;
29use reactive_graph_graph::PropertyInstanceGetter;
30use reactive_graph_graph::PropertyInstances;
31use reactive_graph_graph::PropertyTypeContainer;
32use reactive_graph_graph::PropertyTypeDefinition;
33use reactive_graph_graph::TypeDefinitionComponent;
34use reactive_graph_graph::TypeDefinitionGetter;
35use reactive_graph_graph::TypeDefinitionProperty;
36use reactive_graph_lifecycle::Lifecycle;
37use reactive_graph_reactive_model_api::ReactivePropertyContainer;
38use reactive_graph_reactive_model_impl::ReactiveEntity;
39use reactive_graph_reactive_service_api::ReactiveEntityComponentAddError;
40use reactive_graph_reactive_service_api::ReactiveEntityCreationError;
41use reactive_graph_reactive_service_api::ReactiveEntityManager;
42use reactive_graph_reactive_service_api::ReactiveEntityPropertyAddError;
43use reactive_graph_reactive_service_api::ReactiveEntityPropertyRemoveError;
44use reactive_graph_reactive_service_api::ReactiveEntityRegistrationError;
45use reactive_graph_reactive_service_api::ReactiveInstanceEvent;
46use reactive_graph_reactive_service_api::ReactiveInstanceEventManager;
47use reactive_graph_reactive_service_api::event_channels::EventChannels;
48use reactive_graph_runtime_model::EventProperties::EVENT;
49use reactive_graph_runtime_model::LabeledProperties::LABEL;
50use reactive_graph_type_system_api::ComponentManager;
51use reactive_graph_type_system_api::EntityTypeManager;
52use reactive_graph_type_system_api::TypeSystemEventManager;
53use reactive_graph_type_system_api::TypeSystemEventSubscriber;
54use reactive_graph_type_system_api::TypeSystemEventTypes;
55
56static HANDLE_ID_ENTITY_TYPE_COMPONENT_ADDED: u128 = 0x6ba7b8109e1513d350b300c04fe530c7;
57static HANDLE_ID_ENTITY_TYPE_COMPONENT_REMOVED: u128 = 0x6ba8b8119e1513d350b300c04fe630c7;
58static HANDLE_ID_ENTITY_TYPE_PROPERTY_ADDED: u128 = 0x6ba7b8109e2613d350b300c04fe640c7;
59static HANDLE_ID_ENTITY_TYPE_PROPERTY_REMOVED: u128 = 0x7ca8b8119e1523d361b311c050e630c7;
60
61fn create_label_path_tree() -> RwLock<PathTree<Uuid>> {
62 RwLock::new(PathTree::<Uuid>::new())
63}
64
65fn create_running_state() -> Arc<AtomicBool> {
66 Arc::new(AtomicBool::new(true))
67}
68
69fn create_event_channels() -> EventChannels {
70 let event_channels = EventChannels::new();
71 event_channels.insert(HANDLE_ID_ENTITY_TYPE_COMPONENT_ADDED, crossbeam::channel::unbounded());
72 event_channels.insert(HANDLE_ID_ENTITY_TYPE_COMPONENT_REMOVED, crossbeam::channel::unbounded());
73 event_channels.insert(HANDLE_ID_ENTITY_TYPE_PROPERTY_ADDED, crossbeam::channel::unbounded());
74 event_channels.insert(HANDLE_ID_ENTITY_TYPE_PROPERTY_REMOVED, crossbeam::channel::unbounded());
75 event_channels
76}
77
78#[derive(Component)]
79pub struct ReactiveEntityManagerImpl {
80 reactive_instance_event_manager: Arc<dyn ReactiveInstanceEventManager + Send + Sync>,
81
82 type_system_event_manager: Arc<dyn TypeSystemEventManager + Send + Sync>,
83
84 component_manager: Arc<dyn ComponentManager + Send + Sync>,
85
86 entity_type_manager: Arc<dyn EntityTypeManager + Send + Sync>,
87
88 entity_behaviour_manager: Arc<dyn EntityBehaviourManager + Send + Sync>,
89
90 entity_component_behaviour_manager: Arc<dyn EntityComponentBehaviourManager + Send + Sync>,
91
92 #[component(default = "DashMap::new")]
93 reactive_entity_instances: DashMap<Uuid, ReactiveEntity>,
94
95 #[component(default = "create_label_path_tree")]
96 label_path_tree: RwLock<PathTree<Uuid>>,
97
98 #[component(default = "create_running_state")]
99 running: Arc<AtomicBool>,
100
101 #[component(default = "create_event_channels")]
102 event_channels: EventChannels,
103 }
105
106#[async_trait]
107#[component_alias]
108impl ReactiveEntityManager for ReactiveEntityManagerImpl {
109 fn has(&self, id: Uuid) -> bool {
110 self.reactive_entity_instances.contains_key(&id)
111 }
112
113 fn get(&self, id: Uuid) -> Option<ReactiveEntity> {
114 self.reactive_entity_instances.get(&id).map(|entity_instance| entity_instance.value().clone())
115 }
116
117 fn get_by_label(&self, label: &str) -> Option<ReactiveEntity> {
118 let reader = self.label_path_tree.read().unwrap();
119 reader.find(label).and_then(|result| self.get(*result.0))
120 }
121
122 fn get_by_label_with_params(&self, label: &str) -> Option<(ReactiveEntity, HashMap<String, String>)> {
123 let reader = self.label_path_tree.read().unwrap();
124 reader.find(label).and_then(|result| match self.get(*result.0) {
125 Some(instance) => {
126 let params = result.1.params_iter().map(|param| (param.0.to_string(), param.1.to_string())).collect();
127 Some((instance, params))
128 }
129 None => None,
130 })
131 }
132
133 fn get_all(&self) -> Vec<ReactiveEntity> {
134 self.reactive_entity_instances.iter().map(|e| e.value().clone()).collect()
135 }
136
137 fn get_by_type(&self, ty: &EntityTypeId) -> Vec<ReactiveEntity> {
138 self.reactive_entity_instances
139 .iter()
140 .filter(|e| &e.ty == ty)
141 .map(|e| e.value().clone())
142 .collect()
143 }
144
145 fn get_by_component(&self, ty: &ComponentTypeId) -> Vec<ReactiveEntity> {
146 self.reactive_entity_instances
147 .iter()
148 .filter(|e| e.is_a(ty))
149 .map(|e| e.value().clone())
150 .collect()
151 }
152
153 fn get_by_behaviour(&self, behaviour_ty: &BehaviourTypeId) -> Vec<ReactiveEntity> {
154 self.reactive_entity_instances
155 .iter()
156 .filter(|e| e.behaves_as(behaviour_ty))
157 .map(|e| e.value().clone())
158 .collect()
159 }
160
161 fn get_by_namespace(&self, namespace: &str) -> Vec<ReactiveEntity> {
162 self.reactive_entity_instances
163 .iter()
164 .filter(|r| r.namespace() == namespace)
165 .map(|r| r.value().clone())
166 .collect()
167 }
168
169 fn count(&self) -> usize {
170 self.reactive_entity_instances.len()
171 }
172
173 fn count_by_type(&self, ty: &EntityTypeId) -> usize {
174 self.reactive_entity_instances.iter().filter(|e| &e.ty == ty).count()
175 }
176
177 fn count_by_component(&self, component_ty: &ComponentTypeId) -> usize {
178 self.reactive_entity_instances.iter().filter(|e| e.is_a(component_ty)).count()
179 }
180
181 fn count_by_behaviour(&self, behaviour_ty: &BehaviourTypeId) -> usize {
182 self.reactive_entity_instances.iter().filter(|e| e.behaves_as(behaviour_ty)).count()
183 }
184
185 fn get_ids(&self) -> Vec<Uuid> {
186 self.reactive_entity_instances.iter().map(|e| *e.key()).collect()
187 }
188
189 fn create_reactive_entity(&self, ty: &EntityTypeId, properties: PropertyInstances) -> Result<ReactiveEntity, ReactiveEntityCreationError> {
190 let entity_instance = EntityInstance::builder().ty(ty.clone()).properties(properties).build();
191 self.create_reactive_instance(entity_instance)
192 }
193
194 fn create_with_id(&self, ty: &EntityTypeId, id: Uuid, properties: PropertyInstances) -> Result<ReactiveEntity, ReactiveEntityCreationError> {
195 if self.has(id) {
196 return Err(ReactiveEntityCreationError::UuidTaken(id));
197 }
198
199 let entity_instance = EntityInstance::builder().ty(ty.clone()).id(id).properties(properties).build();
200 self.create_reactive_instance(entity_instance)
201 }
202
203 fn create_reactive_instance(&self, entity_instance: EntityInstance) -> Result<ReactiveEntity, ReactiveEntityCreationError> {
204 let reactive_entity = ReactiveEntity::from(entity_instance);
205
206 if let Some(entity_type) = self.entity_type_manager.get(&reactive_entity.ty) {
208 for component_ty in entity_type.components {
209 if let Some(component) = self.component_manager.get(&component_ty) {
210 for property_type in component.properties.iter() {
211 if let Some(mut property) = reactive_entity.properties.get_mut(&property_type.name) {
212 property.set_mutability(property_type.mutability);
213 }
214 }
215 }
216 }
217 for property_type in entity_type.properties.iter() {
218 if let Some(mut property) = reactive_entity.properties.get_mut(&property_type.name) {
219 property.set_mutability(property_type.mutability);
220 }
221 }
222 }
223
224 self.register_reactive_instance(reactive_entity)
225 .map_err(ReactiveEntityCreationError::ReactiveEntityRegistrationError)
226 }
227
228 fn register_reactive_instance(&self, reactive_entity: ReactiveEntity) -> Result<ReactiveEntity, ReactiveEntityRegistrationError> {
229 if self.reactive_entity_instances.contains_key(&reactive_entity.id) {
230 return Err(ReactiveEntityRegistrationError::UuidTaken(reactive_entity.id));
231 }
232 if !self.entity_type_manager.has(&reactive_entity.ty) {
233 return Err(ReactiveEntityRegistrationError::UnknownEntityType(reactive_entity.ty.clone()));
234 }
235 self.reactive_entity_instances.insert(reactive_entity.id, reactive_entity.clone());
236 if let Some(components) = self.entity_type_manager.get(&reactive_entity.ty).map(|entity_type| entity_type.components) {
238 components.iter().for_each(|component_ty| {
239 reactive_entity.components.insert(component_ty.clone());
240 });
241 }
242 self.entity_component_behaviour_manager.add_behaviours_to_entity(reactive_entity.clone());
244 self.entity_behaviour_manager.add_behaviours(reactive_entity.clone());
246 if let Some(value) = reactive_entity.get(LABEL.property_name()).and_then(|v| v.as_str().map(|s| s.to_string())) {
248 let mut writer = self.label_path_tree.write().unwrap();
249 let _ = writer.insert(&value, reactive_entity.id);
250 }
251 self.reactive_instance_event_manager
252 .emit_event(ReactiveInstanceEvent::EntityInstanceCreated(reactive_entity.id));
253 Ok(reactive_entity)
254 }
292
293 fn register_or_merge_reactive_instance(&self, entity_instance: ReactiveEntity) -> Result<ReactiveEntity, ReactiveEntityRegistrationError> {
294 match self.get(entity_instance.id) {
295 None => self.register_reactive_instance(entity_instance),
297 Some(entity_instance) => Ok(entity_instance),
299 }
300 }
301
302 fn add_component(&self, id: Uuid, component_ty: &ComponentTypeId) -> Result<(), ReactiveEntityComponentAddError> {
303 match self.component_manager.get(component_ty) {
304 Some(component) => {
305 match self.get(id) {
306 Some(entity_instance) => {
307 entity_instance.add_component_with_properties(&component);
309 self.entity_component_behaviour_manager
311 .add_behaviours_to_entity_component(entity_instance, component);
312 Ok(())
313 }
314 None => Err(ReactiveEntityComponentAddError::MissingInstance(id)),
315 }
316 }
317 None => Err(ReactiveEntityComponentAddError::MissingComponent(component_ty.clone())),
318 }
319 }
320
321 fn remove_component(&self, id: Uuid, component_ty: &ComponentTypeId) {
322 if let Some(component) = self.component_manager.get(component_ty) {
323 if let Some(entity_instance) = self.get(id) {
324 entity_instance.remove_component(component_ty);
326 self.entity_component_behaviour_manager
329 .remove_behaviours_from_entity_component(entity_instance, component);
330 }
331 }
332 }
333
334 fn add_property(&self, id: Uuid, property_name: &str, mutability: Mutability, value: Value) -> Result<(), ReactiveEntityPropertyAddError> {
335 match self.get(id) {
336 Some(entity_instance) => {
337 if entity_instance.has_property(property_name) {
338 return Err(ReactiveEntityPropertyAddError::PropertyAlreadyExists(property_name.to_string()));
339 }
340 entity_instance.add_property(property_name, mutability, value);
341 Ok(())
342 }
343 None => Err(ReactiveEntityPropertyAddError::MissingInstance(id)),
344 }
345 }
346
347 fn remove_property(&self, id: Uuid, property_name: &str) -> Result<(), ReactiveEntityPropertyRemoveError> {
348 match self.get(id) {
349 Some(entity_instance) => {
350 if !entity_instance.has_property(property_name) {
351 return Err(ReactiveEntityPropertyRemoveError::MissingProperty(property_name.to_string()));
352 }
353 for component_ty in entity_instance.get_components() {
354 if let Some(component) = self.component_manager.get(&component_ty) {
355 if component.has_own_property(property_name) {
356 return Err(ReactiveEntityPropertyRemoveError::PropertyInUseByComponent(property_name.to_string(), component_ty.clone()));
357 }
358 }
359 }
360 entity_instance.remove_property(property_name);
361 Ok(())
362 }
363 None => Err(ReactiveEntityPropertyRemoveError::MissingInstance(id)),
364 }
365 }
366
367 fn add_behaviour_to_all_entity_instances(&self, entity_behaviour_ty: &EntityBehaviourTypeId) {
368 for entity_instance in self.reactive_entity_instances.iter() {
369 if entity_instance.ty == entity_behaviour_ty.entity_ty {
370 self.entity_behaviour_manager
371 .add_behaviour(entity_instance.clone(), &entity_behaviour_ty.behaviour_ty);
372 }
373 }
374 }
375
376 fn add_behaviour_to_all_entity_components(&self, component_behaviour_ty: &ComponentBehaviourTypeId) {
377 for entity_instance in self.reactive_entity_instances.iter() {
378 if entity_instance.components.contains(&component_behaviour_ty.component_ty) {
379 self.entity_component_behaviour_manager
380 .add_behaviour_to_entity_component(entity_instance.clone(), component_behaviour_ty);
381 }
382 }
383 }
384
385 fn delete(&self, id: Uuid) -> bool {
393 let mut result = false;
394 if self.has(id) {
395 result = self.unregister_reactive_instance(id);
397 }
398 self.reactive_instance_event_manager
401 .emit_event(ReactiveInstanceEvent::EntityInstanceDeleted(id));
402 result
403 }
404
405 fn unregister_reactive_instance(&self, id: Uuid) -> bool {
408 match self.get(id) {
409 Some(entity_instance) => {
410 self.entity_behaviour_manager.remove_behaviours(entity_instance.clone());
412 self.entity_component_behaviour_manager.remove_behaviours_from_entity(entity_instance);
414 }
415 None => {
416 self.entity_behaviour_manager.remove_behaviours_by_id(&id);
418 self.entity_component_behaviour_manager.remove_behaviours_by_id(&id);
420 }
421 }
422 self.reactive_entity_instances.remove(&id).is_some()
423 }
424
425 fn handle_component_added_events(&self) {
426 let component_manager = self.component_manager.clone();
427 let component_behaviour_manager = self.entity_component_behaviour_manager.clone();
428 let reactive_entity_instances = self.reactive_entity_instances.clone();
429 let running = self.running.clone();
430 if let Some(receiver) = self.event_channels.receiver(&HANDLE_ID_ENTITY_TYPE_COMPONENT_ADDED) {
431 tokio::spawn(async move {
432 while running.load(Ordering::Relaxed) {
433 match receiver.try_recv() {
434 Ok(type_definition_component_event) => {
435 if let Ok(type_definition_component) = TypeDefinitionComponent::try_from(type_definition_component_event.clone()) {
436 if let Some(component) = component_manager.get(&type_definition_component.component_ty) {
437 for instance in reactive_entity_instances
438 .iter()
439 .filter(|instance| instance.ty.type_definition() == type_definition_component.type_definition)
440 .map(|instance| instance.value().clone())
441 {
442 instance.add_component_with_properties(&component);
443 component_behaviour_manager.add_behaviours_to_entity_component(instance, component.clone());
444 }
445 }
446 }
447 }
448 Err(_) => {
449 sleep(tokio::time::Duration::from_millis(100)).await;
450 }
451 }
452 }
453 });
454 }
455 }
456
457 fn handle_component_removed_events(&self) {
458 let component_manager = self.component_manager.clone();
459 let component_behaviour_manager = self.entity_component_behaviour_manager.clone();
460 let reactive_entity_instances = self.reactive_entity_instances.clone();
461 let running = self.running.clone();
462 if let Some(receiver) = self.event_channels.receiver(&HANDLE_ID_ENTITY_TYPE_COMPONENT_REMOVED) {
463 tokio::spawn(async move {
464 while running.load(Ordering::Relaxed) {
465 match receiver.try_recv() {
466 Ok(type_definition_component_event) => {
467 if let Ok(type_definition_component) = TypeDefinitionComponent::try_from(type_definition_component_event.clone()) {
468 if let Some(component) = component_manager.get(&type_definition_component.component_ty) {
469 for reactive_entity_instance in reactive_entity_instances
470 .iter()
471 .filter(|entity_instance| entity_instance.type_definition() == type_definition_component.type_definition)
472 .map(|entity_instance| entity_instance.value().clone())
473 {
474 reactive_entity_instance.remove_component(&component.ty);
475 component_behaviour_manager.remove_behaviours_from_entity_component(reactive_entity_instance, component.clone());
476 }
477 }
478 }
479 }
480 Err(_) => {
481 sleep(tokio::time::Duration::from_millis(100)).await;
482 }
483 }
484 }
485 });
486 }
487 }
488
489 fn handle_property_added_events(&self) {
490 let entity_type_manager = self.entity_type_manager.clone();
491 let reactive_entity_instances = self.reactive_entity_instances.clone();
492 let running = self.running.clone();
493 if let Some(receiver) = self.event_channels.receiver(&HANDLE_ID_ENTITY_TYPE_PROPERTY_ADDED) {
494 tokio::spawn(async move {
495 while running.load(Ordering::Relaxed) {
496 match receiver.try_recv() {
497 Ok(type_definition_property_event) => {
498 if let Ok(type_definition_property) = TypeDefinitionProperty::try_from(type_definition_property_event.clone()) {
499 if let Ok(entity_ty) = EntityTypeId::try_from(&type_definition_property.type_definition) {
500 if let Some(entity_type) = entity_type_manager.get(&entity_ty) {
501 for reactive_entity_instance in reactive_entity_instances
502 .iter()
503 .filter(|entity_instance| entity_instance.ty == entity_ty)
504 .map(|entity_instance| entity_instance.value().clone())
505 {
506 if let Some(property_type) = entity_type.get_own_property(&type_definition_property.property) {
507 reactive_entity_instance.add_property_by_type(&property_type);
508 }
509 }
510 }
511 }
512 }
513 }
514 Err(_) => {
515 sleep(tokio::time::Duration::from_millis(100)).await;
516 }
517 }
518 }
519 });
520 }
521 }
522
523 fn handle_property_removed_events(&self) {
524 let reactive_entity_instances = self.reactive_entity_instances.clone();
525 let running = self.running.clone();
526 if let Some(receiver) = self.event_channels.receiver(&HANDLE_ID_ENTITY_TYPE_PROPERTY_REMOVED) {
527 tokio::spawn(async move {
528 while running.load(Ordering::Relaxed) {
529 match receiver.try_recv() {
530 Ok(type_definition_property_event) => {
531 if let Ok(type_definition_property) = TypeDefinitionProperty::try_from(type_definition_property_event.clone()) {
532 if let Ok(entity_ty) = EntityTypeId::try_from(&type_definition_property.type_definition) {
533 for reactive_entity_instance in reactive_entity_instances
534 .iter()
535 .filter(|entity_instance| entity_instance.ty == entity_ty)
536 .map(|entity_instance| entity_instance.value().clone())
537 {
538 reactive_entity_instance.remove_property(&type_definition_property.property);
539 }
540 }
541 }
542 }
543 Err(_) => {
544 sleep(tokio::time::Duration::from_millis(100)).await;
545 }
546 }
547 }
548 });
549 }
550 }
551}
552
553impl TypeSystemEventSubscriber for ReactiveEntityManagerImpl {
554 fn subscribe_type_system_event(&self, event_type: TypeSystemEventTypes, handle_id: u128) {
555 if let Some(entity_instance) = self.type_system_event_manager.get_type_system_event_instance(event_type) {
556 if let Some(sender) = self.event_channels.sender(&handle_id) {
557 entity_instance.observe_with_handle(
558 &EVENT.property_name(),
559 move |v| {
560 let _ = sender.send(v.clone());
561 },
562 handle_id,
563 );
564 }
565 }
566 }
567
568 fn unsubscribe_type_system_event(&self, event_type: TypeSystemEventTypes, handle_id: u128) {
569 if let Some(entity_instance) = self.type_system_event_manager.get_type_system_event_instance(event_type) {
570 entity_instance.remove_observer(&EVENT.property_name(), handle_id);
571 }
572 }
573}
574
575#[async_trait]
576impl Lifecycle for ReactiveEntityManagerImpl {
577 async fn post_init(&self) {
578 for type_system_event_instance in self.type_system_event_manager.get_type_system_event_instances() {
579 if let Err(e) = self.register_reactive_instance(type_system_event_instance) {
580 error!("Failed to register type system event instance: {e:?}");
581 }
583 }
584
585 for reactive_instance_event_instance in self.reactive_instance_event_manager.get_reactive_instance_event_instances() {
586 if let Err(e) = self.register_reactive_instance(reactive_instance_event_instance) {
587 error!("Failed to register reactive instance event instance: {e:?}");
588 }
590 }
591
592 self.subscribe_type_system_event(TypeSystemEventTypes::EntityTypeComponentAdded, HANDLE_ID_ENTITY_TYPE_COMPONENT_ADDED);
593 self.subscribe_type_system_event(TypeSystemEventTypes::EntityTypeComponentRemoved, HANDLE_ID_ENTITY_TYPE_COMPONENT_REMOVED);
594 self.subscribe_type_system_event(TypeSystemEventTypes::EntityTypePropertyAdded, HANDLE_ID_ENTITY_TYPE_PROPERTY_ADDED);
595 self.subscribe_type_system_event(TypeSystemEventTypes::EntityTypePropertyRemoved, HANDLE_ID_ENTITY_TYPE_PROPERTY_REMOVED);
596
597 self.handle_component_added_events();
598 self.handle_component_removed_events();
599 self.handle_property_added_events();
600 self.handle_property_removed_events();
601 }
602
603 async fn pre_shutdown(&self) {
604 self.running.store(false, Ordering::Relaxed);
605
606 self.unsubscribe_type_system_event(TypeSystemEventTypes::EntityTypePropertyRemoved, HANDLE_ID_ENTITY_TYPE_PROPERTY_REMOVED);
607 self.unsubscribe_type_system_event(TypeSystemEventTypes::EntityTypePropertyAdded, HANDLE_ID_ENTITY_TYPE_PROPERTY_ADDED);
608 self.unsubscribe_type_system_event(TypeSystemEventTypes::EntityTypeComponentRemoved, HANDLE_ID_ENTITY_TYPE_COMPONENT_REMOVED);
609 self.unsubscribe_type_system_event(TypeSystemEventTypes::EntityTypeComponentAdded, HANDLE_ID_ENTITY_TYPE_COMPONENT_ADDED);
610 for event_instance in self.reactive_instance_event_manager.get_reactive_instance_event_instances() {
611 self.unregister_reactive_instance(event_instance.id);
612 }
613 for event_instance in self.type_system_event_manager.get_type_system_event_instances() {
614 self.unregister_reactive_instance(event_instance.id);
615 }
616 }
617}
618
619#[cfg(test)]
620mod tests {
621 use default_test::DefaultTest;
622
623 #[allow(unused_imports)]
625 use reactive_graph_behaviour_service_impl::BehaviourSystemImpl;
626 use reactive_graph_graph::EntityType;
627 use reactive_graph_graph::EntityTypeId;
628 use reactive_graph_graph::PropertyTypes;
629 use reactive_graph_reactive_model_impl::ReactiveEntity;
630 use reactive_graph_reactive_service_api::ReactiveSystem;
631 use reactive_graph_utils_test::r_string;
632 #[allow(unused_imports)]
634 use reactive_graph_type_system_impl::TypeSystemImpl;
635
636 use crate::ReactiveSystemImpl;
637
638 #[test]
639 fn test_register_reactive_entity_instance() {
640 reactive_graph_utils_test::init_logger();
641
642 let reactive_system = reactive_graph_di::get_container::<ReactiveSystemImpl>();
643 let type_system = reactive_system.type_system();
644
645 let entity_type_manager = type_system.get_entity_type_manager();
646 let reactive_entity_manager = reactive_system.get_reactive_entity_manager();
647
648 let entity_type = EntityType::default_test();
649 let reactive_entity = ReactiveEntity::builder_from_entity_type(&entity_type).build();
650
651 assert!(reactive_entity_manager.register_reactive_instance(reactive_entity.clone()).is_err());
653 assert!(!reactive_entity_manager.has(reactive_entity.id), "There shouldn't be a reactive entity with the id");
655
656 let entity_type = entity_type_manager.register(entity_type).expect("Failed to register entity type");
658 let reactive_entity = reactive_entity_manager
660 .register_reactive_instance(reactive_entity)
661 .expect("Failed to register the reactive entity");
662 assert!(
664 reactive_entity_manager.has(reactive_entity.id),
665 "The reactive entity with the id should be known by the reactive_entity_manager!"
666 );
667 let id = reactive_entity.id;
669 let reactive_entity = reactive_entity_manager
670 .get(reactive_entity.id)
671 .expect("Failed to get the reactive entity by id!");
672 assert_eq!(id, reactive_entity.id, "The id of the reactive entity doesn't match!");
673 assert_eq!(entity_type.ty, reactive_entity.ty, "The entity type id doesn't match!");
674 }
675
676 #[test]
677 fn test_unregister_reactive_entity_instance() {
678 reactive_graph_utils_test::init_logger();
679
680 let reactive_system = reactive_graph_di::get_container::<ReactiveSystemImpl>();
681 let type_system = reactive_system.type_system();
682 let entity_type_manager = type_system.get_entity_type_manager();
683 let reactive_entity_manager = reactive_system.get_reactive_entity_manager();
684
685 let entity_type = EntityType::builder()
686 .ty(EntityTypeId::default_test())
687 .properties(PropertyTypes::new_with_string_property(r_string()))
688 .build();
689 let entity_type = entity_type_manager.register(entity_type).expect("Failed to register entity type");
691
692 let reactive_entity = ReactiveEntity::builder_from_entity_type(&entity_type).build();
693 let id = reactive_entity.id;
694
695 let _reactive_entity = reactive_entity_manager
697 .register_reactive_instance(reactive_entity)
698 .expect("Failed to register the reactive entity");
699
700 assert!(reactive_entity_manager.has(id), "The reactive entity should be registered!");
701 assert!(reactive_entity_manager.unregister_reactive_instance(id), "The reactive entity should have been unregistered!");
702 assert!(!reactive_entity_manager.has(id), "The reactive entity shouldn't be registered anymore!");
703 }
704
705 #[test]
706 fn test_not_register_twice_reactive_entity_instance() {
707 reactive_graph_utils_test::init_logger();
708
709 let reactive_system = reactive_graph_di::get_container::<ReactiveSystemImpl>();
710 let type_system = reactive_system.type_system();
711 let entity_type_manager = type_system.get_entity_type_manager();
712 let reactive_entity_manager = reactive_system.get_reactive_entity_manager();
713
714 let entity_type = EntityType::builder()
715 .ty(EntityTypeId::default_test())
716 .properties(PropertyTypes::new_with_string_property(r_string()))
717 .build();
718
719 let reactive_entity = ReactiveEntity::builder_from_entity_type(&entity_type).build();
720 let id = reactive_entity.id;
721
722 assert!(
724 reactive_entity_manager.register_reactive_instance(reactive_entity.clone()).is_err(),
725 "The reactive entity shouldn't have been registered because the entity type was not registered!"
726 );
727
728 assert!(!reactive_entity_manager.has(id), "There shouldn't be a reactive entity with id!");
729 assert_eq!(reactive_entity_manager.count(), 0);
730
731 let _entity_type = entity_type_manager.register(entity_type).expect("Failed to register entity type");
733
734 let reactive_entity = reactive_entity_manager
735 .register_reactive_instance(reactive_entity)
736 .expect("Failed to register the reactive entity!");
737
738 assert!(reactive_entity_manager.has(id), "The reactive entity with id should be registered!");
739 assert_eq!(reactive_entity_manager.count(), 1);
740
741 assert!(
742 reactive_entity_manager.register_reactive_instance(reactive_entity).is_err(),
743 "The reactive entity was registered twice!"
744 );
745
746 assert!(reactive_entity_manager.has(id), "The reactive entity with id should be registered!");
747 assert_eq!(reactive_entity_manager.count(), 1);
748 }
749}