Browse Source

Add SerializableFactory class

- add SerializableFactory class to offer the possibility to create an ISerializable reference
- add test coverage for SerializableFactory class
- extend Lynar Studios code style
Patrick-Christopher Mattulat 2 years ago
parent
commit
ce721a93b4

+ 4 - 1
CMakeLists.txt

@@ -97,6 +97,7 @@ set(SOURCE_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/io/kv/KVDocument.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/io/kv/KVParser.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/io/kv/KVReader.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/factory/serialization/SerializableFactory.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/ls_std/factory/serialization/boxing/SerializableJSONBooleanFactory.cpp)
 
 if (${LS_STD_BUILD_WITH_TESTS})
@@ -157,7 +158,9 @@ if (${LS_STD_BUILD_WITH_TESTS})
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/kv/KVDocumentTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/kv/KVParserTest.cpp
             ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/io/kv/KVReaderTest.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/factory/serialization/boxing/SerializableJSONBooleanFactoryTest.cpp)
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/factory/serialization/SerializableFactoryTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/factory/serialization/boxing/SerializableJSONBooleanFactoryTest.cpp
+            ${CMAKE_CURRENT_SOURCE_DIR}/test/classes/factory/SerializableTestFactory.cpp)
 endif ()
 
 ##########################################################

+ 1 - 0
config/LynarStudiosStyle.xml

@@ -37,6 +37,7 @@
     <option name="BRACE_STYLE" value="2" />
     <option name="CLASS_BRACE_STYLE" value="2" />
     <option name="ELSE_ON_NEW_LINE" value="true" />
+    <option name="CATCH_ON_NEW_LINE" value="true" />
     <indentOptions>
       <option name="INDENT_SIZE" value="2" />
       <option name="CONTINUATION_INDENT_SIZE" value="4" />

+ 43 - 0
include/ls_std/factory/serialization/SerializableFactory.hpp

@@ -0,0 +1,43 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2021-04-24
+ * Changed:         2021-04-24
+ *
+ * */
+
+#ifndef LS_STD_SERIALIZABLE_FACTORY_HPP
+#define LS_STD_SERIALIZABLE_FACTORY_HPP
+
+#include <ls_std/base/Class.hpp>
+#include <map>
+#include <string>
+#include <memory>
+#include <ls_std/factory/IFactory.hpp>
+
+namespace ls_std
+{
+  class SerializableFactory : public ls_std::Class
+  {
+    public:
+
+      SerializableFactory();
+      ~SerializableFactory() override = default;
+
+      bool addFactory(const std::pair<std::string, std::shared_ptr<ls_std::IFactory>> &_factoryInsertion);
+      std::shared_ptr<ls_std::Class> build(const std::string &_relatedObjectName);
+      bool clear();
+      bool hasFactory(const std::string &_relatedObjectName);
+      bool removeFactory(const std::string &_relatedObjectName);
+
+    private:
+
+      std::map<std::string, std::shared_ptr<ls_std::IFactory>> factories{};
+
+      bool _hasFactory(const std::string &_relatedObjectName);
+      void _init();
+  };
+}
+
+#endif

+ 2 - 1
include/ls_std/ls_std.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-10-29
- * Changed:         2021-04-23
+ * Changed:         2021-04-24
  *
  * */
 
@@ -92,6 +92,7 @@
 #include "event/EventManager.hpp"
 
 #include "factory/IFactory.hpp"
+#include "factory/serialization/SerializableFactory.hpp"
 #include "factory/serialization/boxing/SerializableJSONBooleanFactory.hpp"
 
 #endif

+ 87 - 0
source/ls_std/factory/serialization/SerializableFactory.cpp

@@ -0,0 +1,87 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2021-04-24
+ * Changed:         2021-04-24
+ *
+ * */
+
+#include <ls_std/factory/serialization/SerializableFactory.hpp>
+#include <ls_std/boxing/Boolean.hpp>
+#include <ls_std/factory/serialization/boxing/SerializableJSONBooleanFactory.hpp>
+#include <ls_std/exception/IllegalArgumentException.hpp>
+#include <ls_std/exception/NullPointerException.hpp>
+
+ls_std::SerializableFactory::SerializableFactory() : ls_std::Class("SerializableFactory")
+{
+  this->_init();
+}
+
+bool ls_std::SerializableFactory::addFactory(const std::pair<std::string, std::shared_ptr<ls_std::IFactory>> &_factoryInsertion)
+{
+  bool hasFactory{};
+
+  if (_factoryInsertion.first.empty())
+  {
+    throw ls_std::IllegalArgumentException{};
+  }
+
+  if (_factoryInsertion.second == nullptr)
+  {
+    throw ls_std::NullPointerException{};
+  }
+
+  if (!this->_hasFactory(_factoryInsertion.first))
+  {
+    hasFactory = this->factories.insert(_factoryInsertion).second;
+  }
+
+  return hasFactory;
+}
+
+std::shared_ptr<ls_std::Class> ls_std::SerializableFactory::build(const std::string &_relatedObjectName)
+{
+  std::shared_ptr<ls_std::Class> requestedObject{};
+
+  if (this->_hasFactory(_relatedObjectName))
+  {
+    requestedObject = this->factories.at(_relatedObjectName)->build();
+  }
+
+  return requestedObject;
+}
+
+bool ls_std::SerializableFactory::clear()
+{
+  this->factories.clear();
+  return factories.empty();
+}
+
+bool ls_std::SerializableFactory::hasFactory(const std::string &_relatedObjectName)
+{
+  return this->_hasFactory(_relatedObjectName);
+}
+
+bool ls_std::SerializableFactory::removeFactory(const std::string &_relatedObjectName)
+{
+  bool wasRemoved{};
+
+  if (this->_hasFactory(_relatedObjectName))
+  {
+    this->factories.erase(_relatedObjectName);
+    wasRemoved = !this->_hasFactory(_relatedObjectName);
+  }
+
+  return wasRemoved;
+}
+
+bool ls_std::SerializableFactory::_hasFactory(const std::string &_relatedObjectName)
+{
+  return this->factories.find(_relatedObjectName) != this->factories.end();
+}
+
+void ls_std::SerializableFactory::_init()
+{
+  this->factories.insert({ls_std::Boolean{}.getClassName(), std::make_shared<ls_std::SerializableJSONBooleanFactory>()});
+}

+ 129 - 0
test/cases/factory/serialization/SerializableFactoryTest.cpp

@@ -0,0 +1,129 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2021-04-24
+ * Changed:         2021-04-24
+ *
+ * */
+
+#include <gtest/gtest.h>
+#include <ls_std/ls_std.hpp>
+#include <ls_std_test.hpp>
+
+namespace
+{
+  class SerializableFactoryTest : public ::testing::Test
+  {
+    protected:
+
+      SerializableFactoryTest() = default;
+      ~SerializableFactoryTest() override = default;
+
+      void SetUp() override
+      {}
+
+      void TearDown() override
+      {}
+  };
+
+  TEST_F(SerializableFactoryTest, addFactory)
+  {
+    std::shared_ptr<ls_std_test::SerializableTestFactory> serializableTestFactory = std::make_shared<ls_std_test::SerializableTestFactory>();
+    ls_std::SerializableFactory serializableFactory{};
+
+    ASSERT_TRUE(serializableFactory.addFactory({"TestClass", serializableTestFactory}));
+  }
+
+  TEST_F(SerializableFactoryTest, addFactory_emptyKey)
+  {
+    std::shared_ptr<ls_std_test::SerializableTestFactory> serializableTestFactory = std::make_shared<ls_std_test::SerializableTestFactory>();
+    ls_std::SerializableFactory serializableFactory{};
+
+    EXPECT_THROW({
+                   try
+                   {
+                     serializableFactory.addFactory({"", serializableTestFactory});
+                   }
+                   catch (const ls_std::IllegalArgumentException &_exception)
+                   {
+                     EXPECT_STREQ("IllegalArgumentException thrown - passed argument is not valid!", _exception.what());
+                     throw;
+                   }
+                 }, ls_std::IllegalArgumentException);
+  }
+
+  TEST_F(SerializableFactoryTest, addFactory_nullPointerValueForFactory)
+  {
+    std::shared_ptr<ls_std_test::SerializableTestFactory> serializableTestFactory{};
+    ls_std::SerializableFactory serializableFactory{};
+
+    EXPECT_THROW({
+                   try
+                   {
+                     serializableFactory.addFactory({"TestClass", serializableTestFactory});
+                   }
+                   catch (const ls_std::NullPointerException &_exception)
+                   {
+                     EXPECT_STREQ("NullPointerException thrown - reference is null!", _exception.what());
+                     throw;
+                   }
+                 }, ls_std::NullPointerException);
+  }
+
+  TEST_F(SerializableFactoryTest, addFactory_dublicatedElement)
+  {
+    std::shared_ptr<ls_std_test::SerializableTestFactory> serializableTestFactory = std::make_shared<ls_std_test::SerializableTestFactory>();
+    ls_std::SerializableFactory serializableFactory{};
+
+    ASSERT_TRUE(serializableFactory.addFactory({"TestClass", serializableTestFactory}));
+    ASSERT_FALSE(serializableFactory.addFactory({"TestClass", serializableTestFactory}));
+  }
+
+  TEST_F(SerializableFactoryTest, build)
+  {
+    ls_std::SerializableFactory serializableFactory{};
+    std::shared_ptr<ls_std::Class> serializable = serializableFactory.build(ls_std::Boolean{}.getClassName());
+
+    ASSERT_TRUE(serializable != nullptr);
+    ASSERT_STREQ(ls_std::Boolean{}.getClassName().c_str(), serializable->getClassName().c_str());
+  }
+
+  TEST_F(SerializableFactoryTest, build_factoryNotAvailable)
+  {
+    ls_std::SerializableFactory serializableFactory{};
+    std::shared_ptr<ls_std::Class> serializable = serializableFactory.build(ls_std_test::GossipNewsAgency{}.getClassName());
+
+    ASSERT_FALSE(serializable != nullptr);
+  }
+
+  TEST_F(SerializableFactoryTest, clear)
+  {
+    ls_std::SerializableFactory serializableFactory{};
+    ASSERT_TRUE(serializableFactory.clear());
+  }
+
+  TEST_F(SerializableFactoryTest, hasFactory)
+  {
+    ls_std::SerializableFactory serializableFactory{};
+    ASSERT_TRUE(serializableFactory.hasFactory(ls_std::Boolean{}.getClassName()));
+  }
+
+  TEST_F(SerializableFactoryTest, hasFactory_factoryNotAvailable)
+  {
+    ls_std::SerializableFactory serializableFactory{};
+    ASSERT_FALSE(serializableFactory.hasFactory(ls_std_test::GossipNewsAgency{}.getClassName()));
+  }
+
+  TEST_F(SerializableFactoryTest, removeFactory)
+  {
+    ls_std::SerializableFactory serializableFactory{};
+    ASSERT_TRUE(serializableFactory.removeFactory(ls_std::Boolean{}.getClassName()));
+  }
+
+  TEST_F(SerializableFactoryTest, removeFactory_factoryNotAvailable)
+  {
+    ls_std::SerializableFactory serializableFactory{};
+    ASSERT_FALSE(serializableFactory.removeFactory(ls_std_test::GossipNewsAgency{}.getClassName()));
+  }
+}

+ 15 - 0
test/classes/factory/SerializableTestFactory.cpp

@@ -0,0 +1,15 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2021-04-24
+ * Changed:         2021-04-24
+ *
+ * */
+
+#include "SerializableTestFactory.hpp"
+
+std::shared_ptr<ls_std::Class> ls_std_test::SerializableTestFactory::build()
+{
+  return std::make_shared<ls_std::Class>();
+}

+ 28 - 0
test/classes/factory/SerializableTestFactory.hpp

@@ -0,0 +1,28 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2021-04-24s
+ * Changed:         2021-04-24
+ *
+ * */
+
+#ifndef LS_STD_SERIALIZABLE_TEST_FACTORY_HPP
+#define LS_STD_SERIALIZABLE_TEST_FACTORY_HPP
+
+#include <ls_std/factory/IFactory.hpp>
+
+namespace ls_std_test
+{
+  class SerializableTestFactory : public ls_std::IFactory
+  {
+    public:
+
+      SerializableTestFactory() = default;
+      ~SerializableTestFactory() = default;
+
+      std::shared_ptr<ls_std::Class> build() override;
+  };
+}
+
+#endif

+ 3 - 1
test/ls_std_test.hpp

@@ -3,7 +3,7 @@
  * Company:         Lynar Studios
  * E-Mail:          webmaster@lynarstudios.com
  * Created:         2020-11-27
- * Changed:         2020-11-27
+ * Changed:         2021-04-24
  *
  * */
 
@@ -16,4 +16,6 @@
 #include "classes/event/GossipNewsEvent.hpp"
 #include "classes/event/SeriousNewsEvent.hpp"
 
+#include "classes/factory/SerializableTestFactory.hpp"
+
 #endif