reactive_graph_behaviour_service_impl/
entity_component_behaviour_manager_impl.rs

1use std::sync::Arc;
2
3use async_trait::async_trait;
4use log::trace;
5use springtime_di::Component;
6use springtime_di::component_alias;
7use uuid::Uuid;
8
9use reactive_graph_behaviour_model_api::BehaviourConnectFailed;
10use reactive_graph_behaviour_model_api::BehaviourDisconnectFailed;
11use reactive_graph_behaviour_model_api::BehaviourState;
12use reactive_graph_behaviour_model_api::BehaviourTransitionError;
13use reactive_graph_behaviour_model_api::BehaviourTypeId;
14use reactive_graph_behaviour_model_api::ComponentBehaviourTypeId;
15use reactive_graph_behaviour_model_impl::EntityBehaviourStorage;
16use reactive_graph_behaviour_service_api::EntityComponentBehaviourManager;
17use reactive_graph_behaviour_service_api::EntityComponentBehaviourRegistry;
18use reactive_graph_graph::ComponentContainer;
19use reactive_graph_lifecycle::Lifecycle;
20use reactive_graph_reactive_model_impl::ReactiveEntity;
21
22#[derive(Component)]
23pub struct EntityComponentBehaviourManagerImpl {
24    entity_component_behaviour_registry: Arc<dyn EntityComponentBehaviourRegistry + Send + Sync>,
25
26    #[component(default = "EntityBehaviourStorage::new")]
27    entity_behaviour_storage: EntityBehaviourStorage,
28}
29
30#[async_trait]
31#[component_alias]
32impl EntityComponentBehaviourManager for EntityComponentBehaviourManagerImpl {
33    fn add_behaviours_to_entity(&self, entity_instance: ReactiveEntity) {
34        for component_ty in entity_instance.get_components() {
35            for factory in self.entity_component_behaviour_registry.get(&component_ty) {
36                if let Ok(behaviour) = factory.create(entity_instance.clone()) {
37                    let behaviour_ty = behaviour.ty().clone();
38                    self.entity_behaviour_storage.insert(entity_instance.id, behaviour.ty().clone(), behaviour);
39                    trace!("Added entity component behaviour {}", &behaviour_ty);
40                }
41            }
42        }
43    }
44
45    fn add_behaviours_to_entity_component(&self, entity_instance: ReactiveEntity, component: reactive_graph_graph::Component) {
46        for factory in self.entity_component_behaviour_registry.get(&component.ty) {
47            if let Ok(behaviour) = factory.create(entity_instance.clone()) {
48                let behaviour_ty = behaviour.ty().clone();
49                self.entity_behaviour_storage.insert(entity_instance.id, behaviour_ty.clone(), behaviour);
50                trace!("Added entity component behaviour {}", &behaviour_ty);
51            }
52        }
53    }
54
55    fn add_behaviour_to_entity_component(&self, entity_instance: ReactiveEntity, component_behaviour_ty: &ComponentBehaviourTypeId) {
56        for factory in self.entity_component_behaviour_registry.get(&component_behaviour_ty.component_ty) {
57            if let Ok(behaviour) = factory.create(entity_instance.clone()) {
58                let behaviour_ty = behaviour.ty().clone();
59                self.entity_behaviour_storage.insert(entity_instance.id, behaviour_ty.clone(), behaviour);
60                trace!("Added entity component behaviour {}", &behaviour_ty);
61            }
62        }
63    }
64
65    fn remove_behaviour_from_entity(&self, entity_instance: ReactiveEntity, behaviour_ty: &BehaviourTypeId) {
66        let id = entity_instance.id;
67        let _ = self.disconnect(entity_instance, behaviour_ty);
68        self.entity_behaviour_storage.remove(&id, behaviour_ty);
69        trace!("Removed entity behaviour {} from {}", &behaviour_ty, id);
70    }
71
72    fn remove_behaviours_from_entity(&self, entity_instance: ReactiveEntity) {
73        self.entity_behaviour_storage.remove_all(&entity_instance.id);
74    }
75
76    fn remove_behaviours_from_entity_component(&self, entity_instance: ReactiveEntity, component: reactive_graph_graph::Component) {
77        for factory in self.entity_component_behaviour_registry.get(&component.ty) {
78            self.entity_behaviour_storage.remove(&entity_instance.id, factory.behaviour_ty());
79            trace!("Removed entity component behaviour {}", factory.behaviour_ty());
80        }
81    }
82
83    fn remove_behaviours_by_id(&self, id: &Uuid) {
84        self.entity_behaviour_storage.remove_all(id);
85    }
86
87    fn remove_behaviours_by_behaviour(&self, behaviour_ty: &BehaviourTypeId) {
88        self.entity_behaviour_storage.remove_by_behaviour(behaviour_ty);
89        trace!("Removed all entity component behaviours of type {}", &behaviour_ty);
90    }
91
92    fn has(&self, entity_instance: ReactiveEntity, behaviour_ty: &BehaviourTypeId) -> bool {
93        self.entity_behaviour_storage.has(&entity_instance.id, behaviour_ty)
94    }
95
96    fn get_all(&self, entity_instance: ReactiveEntity) -> Vec<BehaviourTypeId> {
97        self.entity_behaviour_storage.get_behaviours_by_instance(&entity_instance.id)
98    }
99
100    fn get_instances_by_behaviour(&self, ty: &BehaviourTypeId) -> Vec<ReactiveEntity> {
101        self.entity_behaviour_storage.get_instances_by_behaviour(ty)
102    }
103
104    fn connect(&self, entity_instance: ReactiveEntity, behaviour_ty: &BehaviourTypeId) -> Result<(), BehaviourTransitionError> {
105        if let Some(fsm) = self.entity_behaviour_storage.get(&entity_instance.id, behaviour_ty) {
106            return fsm.transition(BehaviourState::Connected);
107        }
108        Err(BehaviourTransitionError::BehaviourConnectFailed(BehaviourConnectFailed {}))
109    }
110
111    fn disconnect(&self, entity_instance: ReactiveEntity, behaviour_ty: &BehaviourTypeId) -> Result<(), BehaviourTransitionError> {
112        if let Some(fsm) = self.entity_behaviour_storage.get(&entity_instance.id, behaviour_ty) {
113            return fsm.transition(BehaviourState::Ready);
114        }
115        Err(BehaviourTransitionError::BehaviourDisconnectFailed(BehaviourDisconnectFailed {}))
116    }
117
118    fn reconnect(&self, entity_instance: ReactiveEntity, behaviour_ty: &BehaviourTypeId) -> Result<(), BehaviourTransitionError> {
119        if let Some(fsm) = self.entity_behaviour_storage.get(&entity_instance.id, behaviour_ty) {
120            return fsm.transition(BehaviourState::Ready).and_then(|_| fsm.transition(BehaviourState::Connected));
121        }
122        Err(BehaviourTransitionError::InvalidTransition)
123    }
124}
125
126#[async_trait]
127impl Lifecycle for EntityComponentBehaviourManagerImpl {}