Explorar el Código

Added SerializableXMLState class (unstable)

- added SerializableXMLState class to provide
functionality to convert State class to XML
- added tests for SerializableXMLState class
Patrick-Laptop hace 4 años
padre
commit
5f421f895c

+ 5 - 3
CMakeLists.txt

@@ -109,12 +109,13 @@ set(SOURCE_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/json/logic/SerializableJSONStateMachine.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/xml/logic/SerializableXMLStateConnection.hpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/xml/logic/SerializableXMLStateConnection.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/xml/logic/SerializableXMLState.hpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/serialization/xml/logic/SerializableXMLState.cpp
         )
 
 set(LIBRARY_SOURCE_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/source/lib/tiny_xml_2/include/tinyxml2.h
-        ${CMAKE_CURRENT_SOURCE_DIR}/source/lib/tiny_xml_2/tinyxml2.cpp
-        )
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/lib/tiny_xml_2/tinyxml2.cpp)
 
 set(TEST_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/boxing/IntegerTest.cpp
@@ -151,7 +152,8 @@ set(TEST_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/TestDataFactory.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/xml/RapidXMLTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/xml/TinyXMLTest.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/xml/logic/SerializableXMLStateConnectionTest.cpp)
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/xml/logic/SerializableXMLStateConnectionTest.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/serialization/xml/logic/SerializableXMLStateTest.cpp)
 
 ##########################################################
 # Build

+ 111 - 0
source/serialization/xml/logic/SerializableXMLState.cpp

@@ -0,0 +1,111 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-09-20
+ * Changed:         2020-09-20
+ *
+ * */
+
+#include "SerializableXMLState.hpp"
+#include "../../../boxing/String.hpp"
+#include "SerializableXMLStateConnection.hpp"
+
+ls_std::SerializableXMLState::SerializableXMLState(std::shared_ptr<ls_std::State> _value) :
+Class("SerializableXMLState"),
+value(std::move(_value))
+{}
+
+ls_std::byte_field ls_std::SerializableXMLState::marshal()
+{
+  this->_update();
+  tinyxml2::XMLPrinter printer {};
+  this->document.Print(&printer);
+
+  return printer.CStr();
+}
+
+void ls_std::SerializableXMLState::unmarshal(const ls_std::byte_field &_data)
+{
+  ls_std::String data {_data};
+  this->document.Parse(data.getByteData().data());
+  tinyxml2::XMLElement* root = this->document.RootElement();
+
+  if(root != nullptr ) {
+    this->_unmarshalConnections(root);
+    this->_unmarshalId(root);
+  }
+}
+
+std::shared_ptr<ls_std::State> ls_std::SerializableXMLState::getValue()
+{
+  return this->value;
+}
+
+void ls_std::SerializableXMLState::setValue(std::shared_ptr<ls_std::State> _value)
+{
+  this->value = std::move(_value);
+  this->_clear();
+}
+
+void ls_std::SerializableXMLState::_clear()
+{
+  this->document.Clear();
+}
+
+void ls_std::SerializableXMLState::_unmarshalConnections(tinyxml2::XMLElement *_root)
+{
+  tinyxml2::XMLNode* connections = _root->FirstChildElement("connections");
+
+  if(connections != nullptr) {
+    tinyxml2::XMLNode* connection = connections->FirstChildElement("connection");
+    tinyxml2::XMLPrinter printer{};
+    this->value->clearConnections();
+
+    do {
+     if (connection != nullptr) {
+       connection->Accept(&printer);
+       ls_std::SerializableXMLStateConnection serializable{std::make_shared<ls_std::StateConnection>("", "")};
+       serializable.unmarshal(printer.CStr());
+       this->value->addStateConnection(serializable.getValue());
+       connection = connection->NextSibling();
+       printer.ClearBuffer();
+     }
+    }
+    while(connection != nullptr);
+  }
+}
+
+void ls_std::SerializableXMLState::_unmarshalId(tinyxml2::XMLElement* _root)
+{
+  const tinyxml2::XMLAttribute *attribute = _root->FindAttribute("id");
+
+  if(attribute != nullptr) {
+    this->value->setId(attribute->Value());
+  }
+}
+
+void ls_std::SerializableXMLState::_update()
+{
+  this->_clear();
+  tinyxml2::XMLNode* root = this->document.NewElement("state");
+  this->document.InsertFirstChild(root);
+  root->ToElement()->SetAttribute("id", this->value->getId().c_str());
+  this->_updateStates();
+}
+
+void ls_std::SerializableXMLState::_updateStates()
+{
+  tinyxml2::XMLNode* connectionsNode = this->document.NewElement("connections");
+  tinyxml2::XMLElement* stateNode = this->document.FirstChildElement("state");
+
+  for(const auto& connection : this->value->getConnectedStates()) {
+    ls_std::byte_field data = ls_std::SerializableXMLStateConnection {connection.second}.marshal();
+    tinyxml2::XMLDocument connectionNodeDocument {};
+    connectionNodeDocument.Parse(data.c_str());
+    tinyxml2::XMLNode* connectionNode = connectionNodeDocument.RootElement();
+    connectionsNode->InsertFirstChild(connectionNode);
+  }
+
+  stateNode->InsertEndChild(connectionsNode);
+}

+ 49 - 0
source/serialization/xml/logic/SerializableXMLState.hpp

@@ -0,0 +1,49 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-09-20
+ * Changed:         2020-09-20
+ *
+ * */
+
+#ifndef LS_STD_SERIALIZABLE_XML_STATE_HPP
+#define LS_STD_SERIALIZABLE_XML_STATE_HPP
+
+#include "../../../base/Class.hpp"
+#include "../../ISerializable.hpp"
+#include "../../../logic/State.hpp"
+#include <memory>
+#include <tinyxml2.h>
+
+namespace ls_std {
+  class SerializableXMLState : public Class, public ISerializable {
+    public:
+
+      explicit SerializableXMLState(std::shared_ptr<State> _value);
+      ~SerializableXMLState() = default;
+
+      // implementation
+
+      ls_std::byte_field marshal() override;
+      void unmarshal(const ls_std::byte_field& _data) override;
+
+      // additional functionality
+
+      std::shared_ptr<State> getValue();
+      void setValue(std::shared_ptr<State> _value);
+
+    private:
+
+      tinyxml2::XMLDocument document {};
+      std::shared_ptr<State> value {};
+
+      void _clear();
+      void _unmarshalConnections(tinyxml2::XMLElement* _root);
+      void _unmarshalId(tinyxml2::XMLElement* _root);
+      void _update();
+      void _updateStates();
+  };
+}
+
+#endif

+ 83 - 0
test/cases/serialization/xml/logic/SerializableXMLStateTest.cpp

@@ -0,0 +1,83 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-09-20
+ * Changed:         2020-09-20
+ *
+ * */
+
+#include <gtest/gtest.h>
+#include "../../../../../source/serialization/xml/logic/SerializableXMLState.hpp"
+#include "../../../../../source/boxing/String.hpp"
+
+namespace {
+  class SerializableXMLStateTest : public ::testing::Test {
+    protected:
+
+      SerializableXMLStateTest() = default;
+      ~SerializableXMLStateTest() override = default;
+
+      void SetUp() override {}
+      void TearDown() override {}
+  };
+
+  // implementation
+
+  TEST_F(SerializableXMLStateTest, marshal)
+  {
+    std::shared_ptr<ls_std::State> stateA = std::make_shared<ls_std::State>("A");
+    stateA->addStateConnection(std::make_shared<ls_std::StateConnection>("AB", "B"));
+    stateA->addStateConnection(std::make_shared<ls_std::StateConnection>("AC", "C"));
+    ls_std::SerializableXMLState serializable {stateA};
+
+    std::string data = serializable.marshal();
+    ASSERT_TRUE(!data.empty());
+  }
+
+  TEST_F(SerializableXMLStateTest, unmarshal)
+  {
+    ls_std::SerializableXMLState serializable {std::make_shared<ls_std::State>("A")};
+    std::string xmlText = R"(
+      <state id="B">
+        <connections>
+          <connection connectionId="BC" id="C" condition="true"/>
+          <connection connectionId="BD" id="D" condition="true"/>
+        </connections>
+      </state>)";
+
+    serializable.unmarshal(xmlText);
+    ASSERT_STREQ("B", serializable.getValue()->getId().c_str());
+    auto connections = serializable.getValue()->getConnectedStates();
+
+    ASSERT_EQ(2, connections.size());
+    ASSERT_TRUE(connections.at("BC") != nullptr);
+    ASSERT_TRUE(connections.at("BC")->isPassable());
+    ASSERT_STREQ("BC", connections.at("BC")->getConnectionId().c_str());
+    ASSERT_STREQ("C", connections.at("BC")->getStateId().c_str());
+
+    ASSERT_TRUE(connections.at("BD") != nullptr);
+    ASSERT_TRUE(connections.at("BD")->isPassable());
+    ASSERT_STREQ("BD", connections.at("BD")->getConnectionId().c_str());
+    ASSERT_STREQ("D", connections.at("BD")->getStateId().c_str());
+  }
+
+  // additional functionality
+
+  TEST_F(SerializableXMLStateTest, getValue)
+  {
+    std::shared_ptr<ls_std::State> x = std::make_shared<ls_std::State>("A");
+    ls_std::SerializableXMLState serializable {x};
+
+    ASSERT_STREQ("A", serializable.getValue()->getId().c_str());
+  }
+
+  TEST_F(SerializableXMLStateTest, setValue)
+  {
+    ls_std::SerializableXMLState serializable {std::make_shared<ls_std::State>("A")};
+    ASSERT_STREQ("A", serializable.getValue()->getId().c_str());
+
+    serializable.setValue(std::make_shared<ls_std::State>("C"));
+    ASSERT_STREQ("C", serializable.getValue()->getId().c_str());
+  }
+}