Browse Source

Add EventManager class

- add EventManager class to hold individual
EventHandler
- add tests for EventManager class
Patrick-Christopher Mattulat 3 years ago
parent
commit
19edd38497

+ 4 - 2
CMakeLists.txt

@@ -77,7 +77,8 @@ set(SOURCE_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/logic/IListener.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/io/xml/XMLParser.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/event/Event.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/event/EventHandler.cpp)
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/event/EventHandler.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/event/EventManager.cpp)
 
 set(TEST_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/boxing/IntegerTest.cpp
@@ -129,7 +130,8 @@ set(TEST_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/event/SeriousNewsEvent.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/event/GossipNewsEvent.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/event/GossipNewsAgency.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/event/EventHandlerTest.cpp)
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/event/EventHandlerTest.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/event/EventManagerTest.cpp)
 
 ##########################################################
 # Build

+ 39 - 0
include/ls_std/event/EventManager.hpp

@@ -0,0 +1,39 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-11-27
+ * Changed:         2020-11-27
+ *
+ * */
+
+#ifndef LS_STD_EVENT_MANAGER_HPP
+#define LS_STD_EVENT_MANAGER_HPP
+
+#include <ls_std/base/Class.hpp>
+#include <map>
+#include <ls_std/event/EventTypes.hpp>
+#include <memory>
+#include "EventHandler.hpp"
+
+namespace ls_std {
+  class EventManager : public ls_std::Class {
+    public:
+
+      explicit EventManager();
+      ~EventManager() override = default;
+
+      void addEventHandler(const std::shared_ptr<ls_std::EventHandler>& _eventHandler);
+      void fire(ls_std::Event _event);
+      void removeEventHandler(const std::shared_ptr<ls_std::EventHandler>& _eventHandler);
+
+    private:
+
+      std::map<ls_std::event_id, std::shared_ptr<ls_std::EventHandler>> eventHandlers {};
+
+      bool _hasEventHandler(const ls_std::event_id& _id);
+      void _removeEventHandler(const std::shared_ptr<ls_std::EventHandler>& _eventHandler);
+  };
+}
+
+#endif

+ 1 - 0
include/ls_std/ls_std.hpp

@@ -75,5 +75,6 @@
 #include "event/EventTypes.hpp"
 #include "event/EventHandler.hpp"
 #include "event/IEventSubscriber.hpp"
+#include "event/EventManager.hpp"
 
 #endif

+ 43 - 0
source/ls_std/event/EventManager.cpp

@@ -0,0 +1,43 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-11-27
+ * Changed:         2020-11-27
+ *
+ * */
+
+#include <ls_std/event/EventManager.hpp>
+
+ls_std::EventManager::EventManager() : ls_std::Class("EventManager")
+{}
+
+void ls_std::EventManager::addEventHandler(const std::shared_ptr<ls_std::EventHandler> &_eventHandler)
+{
+  if(!this->_hasEventHandler(_eventHandler->getId())) {
+    std::pair<ls_std::event_id, std::shared_ptr<ls_std::EventHandler>> element = std::make_pair(_eventHandler->getId(), _eventHandler);
+    this->eventHandlers.insert(element);
+  }
+}
+
+void ls_std::EventManager::fire(ls_std::Event _event)
+{
+  if(this->_hasEventHandler(_event.getId())) {
+    this->eventHandlers.at(_event.getId())->notify(_event);
+  }
+}
+
+void ls_std::EventManager::removeEventHandler(const std::shared_ptr<ls_std::EventHandler> &_eventHandler)
+{
+  this->_removeEventHandler(_eventHandler);
+}
+
+bool ls_std::EventManager::_hasEventHandler(const ls_std::event_id &_id)
+{
+  return this->eventHandlers.find(_id) != this->eventHandlers.end();
+}
+
+void ls_std::EventManager::_removeEventHandler(const std::shared_ptr<ls_std::EventHandler> &_eventHandler)
+{
+  this->eventHandlers.erase(_eventHandler->getId());
+}

+ 112 - 0
test/cases/event/EventManagerTest.cpp

@@ -0,0 +1,112 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-11-27
+ * Changed:         2020-11-27
+ *
+ * */
+
+#include <gtest/gtest.h>
+#include <ls_std/ls_std.hpp>
+#include <ls_std_test.hpp>
+
+namespace {
+  class EventManagerTest : public ::testing::Test {
+    protected:
+
+      EventManagerTest() = default;
+      ~EventManagerTest() override = default;
+
+      void SetUp() override
+      {}
+
+      void TearDown() override
+      {}
+  };
+
+  TEST_F(EventManagerTest, getClassName)
+  {
+    ls_std::EventManager eventManager {};
+    ASSERT_STREQ("EventManager", eventManager.getClassName().c_str());
+  }
+
+  TEST_F(EventManagerTest, production_example)
+  {
+    std::string news, expectedNews {};
+    ls_std::event_id seriousNewsEventId = ls_std_test::SeriousNewsEvent {""}.getId();
+    ls_std::event_id gossipNewsEventId = ls_std_test::GossipNewsEvent {""}.getId();
+
+    // create event handler
+
+    std::shared_ptr<ls_std::EventHandler> seriousNewsEventHandler = std::make_shared<ls_std::EventHandler>(seriousNewsEventId);   // event id
+    std::shared_ptr<ls_std::EventHandler> gossipNewsEventHandler = std::make_shared<ls_std::EventHandler>(gossipNewsEventId);     // event id
+
+    // create and fill event manger with handler
+
+    std::shared_ptr<ls_std::EventManager> eventManager = std::make_shared<ls_std::EventManager>();
+    eventManager->addEventHandler(seriousNewsEventHandler);
+    eventManager->addEventHandler(gossipNewsEventHandler);
+
+    // create news agency (listener)
+
+    std::shared_ptr<ls_std_test::DailyNewsAgency> dailyNews = std::make_shared<ls_std_test::DailyNewsAgency>();
+    std::shared_ptr<ls_std_test::GossipNewsAgency> gossipNews = std::make_shared<ls_std_test::GossipNewsAgency>();
+
+    // add handler of those events, every news agency should know
+    // this is how agencies know about events
+
+    dailyNews->addEventHandler(seriousNewsEventHandler);
+
+    gossipNews->addEventHandler(seriousNewsEventHandler);
+    gossipNews->addEventHandler(gossipNewsEventHandler);
+
+    // fire SeriousNewsEvent event with no effect
+
+    eventManager->fire(ls_std_test::SeriousNewsEvent(news)); // event call
+    ASSERT_TRUE(dailyNews->getNews().empty());
+    ASSERT_TRUE(gossipNews->getNews().empty());
+
+    // now subscribe to SeriousNewsEvent and fire SeriousNewsEvent event
+
+    dailyNews->subscribe(seriousNewsEventId);
+    gossipNews->subscribe(seriousNewsEventId);
+    news = "COVID-19 is still going on!";
+    eventManager->fire(ls_std_test::SeriousNewsEvent(news)); // event call
+
+    expectedNews = "DailyNewsAgency: " + news;
+    ASSERT_STREQ(expectedNews.c_str(), dailyNews->getNews().c_str());
+    expectedNews = "GossipNewsAgency: " + news;
+    ASSERT_STREQ(expectedNews.c_str(), gossipNews->getNews().c_str());
+
+    dailyNews->clear();
+    gossipNews->clear();
+
+    // unsubscribe SeriousNewsEvent from GossipNewsAgency
+
+    gossipNews->unsubscribe(seriousNewsEventId);
+    eventManager->fire(ls_std_test::SeriousNewsEvent(news)); // event call
+
+    expectedNews = "DailyNewsAgency: " + news;
+    ASSERT_STREQ(expectedNews.c_str(), dailyNews->getNews().c_str());
+    ASSERT_TRUE(gossipNews->getNews().empty());
+
+    dailyNews->clear();
+    gossipNews->clear();
+
+    // now let GossipNewsAgency subscribe to SeriousNewsEvent + GossipNewsEvent and fire both of them
+
+    gossipNews->subscribe(gossipNewsEventId);
+    gossipNews->subscribe(seriousNewsEventId);
+
+    news = "COVID-19 is still going on!";
+    eventManager->fire(ls_std_test::SeriousNewsEvent(news)); // event call
+    expectedNews = "GossipNewsAgency: " + news;
+    ASSERT_STREQ(expectedNews.c_str(), gossipNews->getNews().c_str());
+
+    news = "ape likes banana!";
+    eventManager->fire(ls_std_test::GossipNewsEvent(news)); // event call
+    expectedNews = "GossipNewsAgency: " + news;
+    ASSERT_STREQ(expectedNews.c_str(), gossipNews->getNews().c_str());
+  }
+}