Browse Source

Added SerializableJSONState class

- added SerializableJSONState class to offer
functionality to serialize State class
- added tests for SerializableJSONState class
Patrick-Laptop 3 years ago
parent
commit
61e7e4ab17

+ 5 - 2
CMakeLists.txt

@@ -100,7 +100,9 @@ set(SOURCE_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/source/logic/StateConnection.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/logic/StateMachineTypes.hpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONStateConnection.hpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONStateConnection.cpp)
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONStateConnection.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONState.hpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONState.cpp)
 
 set(TEST_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/boxing/IntegerTest.cpp
@@ -130,7 +132,8 @@ set(TEST_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/logic/StateTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/logic/StateMachineTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/logic/StateConnectionTest.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/json/logic/SerializableJSONStateConnectionTest.cpp)
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/json/logic/SerializableJSONStateConnectionTest.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/json/logic/SerializableJSONStateTest.cpp)
 
 ##########################################################
 # Build

+ 74 - 0
source/serialization/json/logic/SerializableJSONState.cpp

@@ -0,0 +1,74 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-09-15
+ * Changed:         2020-09-15
+ *
+ * */
+
+#include "SerializableJSONState.hpp"
+#include "SerializableJSONStateConnection.hpp"
+
+ls_std::SerializableJSONState::SerializableJSONState(std::shared_ptr<State> _value) :
+Class("SerializableJSONState"),
+value(std::move(_value))
+{}
+
+ls_std::byte_field ls_std::SerializableJSONState::marshal()
+{
+  this->_update();
+  return this->jsonObject.dump();
+}
+
+void ls_std::SerializableJSONState::unmarshal(const ls_std::byte_field &_data)
+{
+  this->jsonObject = nlohmann::json::parse(_data);
+
+  this->_unmarshalStateConnections();
+  this->value->setId(this->jsonObject["id"]);
+}
+
+void ls_std::SerializableJSONState::_unmarshalExistingStateConnection(nlohmann::json _jsonObject)
+{
+  std::shared_ptr<ls_std::StateConnection> stateConnection = this->value->getConnectedStates().at(_jsonObject["connectionId"]);
+
+  stateConnection->updatePassCondition(_jsonObject["condition"]);
+  stateConnection->setStateId(_jsonObject["stateId"]);
+}
+
+void ls_std::SerializableJSONState::_unmarshalNewStateConnection(nlohmann::json _jsonObject)
+{
+  std::shared_ptr<ls_std::StateConnection> stateConnection = std::make_shared<ls_std::StateConnection>(_jsonObject["connectionId"], _jsonObject["stateId"]);
+  stateConnection->updatePassCondition(_jsonObject["condition"]);
+
+  this->value->addStateConnection(stateConnection);
+}
+
+void ls_std::SerializableJSONState::_unmarshalStateConnections()
+{
+  for(const auto& connectedState : this->jsonObject["connectedStates"]) {
+    if(this->value->hasConnection(connectedState["connectionId"])) {
+      this->_unmarshalExistingStateConnection(connectedState);
+    }
+    else {
+      this->_unmarshalNewStateConnection(connectedState);
+    }
+  }
+}
+
+void ls_std::SerializableJSONState::_update()
+{
+  this->_updateStateConnections();
+  this->jsonObject["id"] = this->value->getId();
+}
+
+void ls_std::SerializableJSONState::_updateStateConnections()
+{
+  ls_std::SerializableJSONStateConnection serializable {nullptr};
+
+  for(const auto& connection : this->value->getConnectedStates()) {
+    serializable.setValue(connection.second);
+    this->jsonObject["connectedStates"][connection.first] = nlohmann::json::parse(serializable.marshal());
+  }
+}

+ 42 - 0
source/serialization/json/logic/SerializableJSONState.hpp

@@ -0,0 +1,42 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-09-15
+ * Changed:         2020-09-15
+ *
+ * */
+
+#ifndef LS_STD_SERIALIZABLE_JSON_STATE_HPP
+#define LS_STD_SERIALIZABLE_JSON_STATE_HPP
+
+#include "../../../base/Class.hpp"
+#include "../../ISerializable.hpp"
+#include "../../../logic/State.hpp"
+#include <memory>
+#include <json.hpp>
+
+namespace ls_std {
+  class SerializableJSONState : public Class, public ISerializable {
+    public:
+
+      explicit SerializableJSONState(std::shared_ptr<State> _value);
+      ~SerializableJSONState() = default;
+
+      ls_std::byte_field marshal() override;
+      void unmarshal(const ls_std::byte_field& _data) override;
+
+    private:
+
+      nlohmann::json jsonObject {};
+      std::shared_ptr<ls_std::State> value {};
+
+      void _unmarshalExistingStateConnection(nlohmann::json _jsonObject);
+      void _unmarshalNewStateConnection(nlohmann::json _jsonObject);
+      void _unmarshalStateConnections();
+      void _update();
+      void _updateStateConnections();
+  };
+}
+
+#endif

+ 61 - 0
test/cases/serialization/json/logic/SerializableJSONStateTest.cpp

@@ -0,0 +1,61 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-09-15
+ * Changed:         2020-09-15
+ *
+ * */
+
+#include <gtest/gtest.h>
+#include "../../../../../source/boxing/String.hpp"
+#include "../../../../../source/logic/State.hpp"
+#include "../../../../../source/serialization/json/logic/SerializableJSONState.hpp"
+
+namespace {
+  class SerializableJSONStateTest : public ::testing::Test {
+    protected:
+
+      SerializableJSONStateTest() = default;
+      ~SerializableJSONStateTest() override = default;
+
+      void SetUp() override {}
+      void TearDown() override {}
+  };
+
+  TEST_F(SerializableJSONStateTest, marshal)
+  {
+    std::shared_ptr<ls_std::State> x = std::make_shared<ls_std::State>("A");
+    x->addStateConnection(std::make_shared<ls_std::StateConnection>("AB", "B"));
+    x->addStateConnection(std::make_shared<ls_std::StateConnection>("AC", "C"));
+
+    ls_std::SerializableJSONState serializable {x};
+    ls_std::byte_field jsonString = serializable.marshal();
+
+    ASSERT_TRUE(!jsonString.empty());
+    std::string expectedJSONString = R"({"connectedStates":{"AB":{"condition":false,"connectionId":"AB","stateId":"B"},"AC":{"condition":false,"connectionId":"AC","stateId":"C"}},"id":"A"})";
+    ASSERT_STREQ(expectedJSONString.c_str(), jsonString.c_str());
+  }
+
+  TEST_F(SerializableJSONStateTest, unmarshal)
+  {
+    std::shared_ptr<ls_std::State> x = std::make_shared<ls_std::State>("A");
+    ls_std::SerializableJSONState serializable {x};
+
+    // before
+
+    ASSERT_STREQ("A", x->getId().c_str());
+    ASSERT_TRUE(x->getConnectedStates().empty());
+
+    // after
+
+    std::string jsonString = R"({"id":"A","connectedStates":{"AB":{"condition":false,"connectionId":"AB","stateId":"B"}}})";
+    serializable.unmarshal(jsonString);
+
+    ASSERT_STREQ("A", x->getId().c_str());
+    ASSERT_EQ(1, x->getConnectedStates().size());
+    ASSERT_STREQ("AB", x->getConnectedStates().at("AB")->getConnectionId().c_str());
+    ASSERT_FALSE(x->getConnectedStates().at("AB")->isPassable());
+    ASSERT_STREQ("B", x->getConnectedStates().at("AB")->getStateId().c_str());
+  }
+}