summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2014-03-06 00:11:17 +0000
committerandreas <andreas@daaaf23c-2e50-4459-9457-1e69db5a47bf>2014-03-06 00:11:17 +0000
commitd99095f4a181357bf0c6d10846351eb0b58b1ccf (patch)
tree74daacc842023b14e27aa49403ee8d4aaa8bb172
parentf098dc45183d2b7a99e65b62448f59d12cc3c056 (diff)
started to implement rudimentary XML reader (implemented expectOneOf function), changed some conventions in the used files (namespaces, include guards), moved anchor class from domain to document package, removed everything that does not work now from the CMakeLists.txt
git-svn-id: file:///var/local/svn/basicwriter@24 daaaf23c-2e50-4459-9457-1e69db5a47bf
-rw-r--r--CMakeLists.txt34
-rw-r--r--src/main.cpp33
-rw-r--r--src/model/GraphNode.cpp20
-rw-r--r--src/model/GraphNode.hpp34
-rw-r--r--src/model/document/Anchor.cpp (renamed from src/model/domain/Anchor.cpp)0
-rw-r--r--src/model/document/Anchor.hpp (renamed from src/model/domain/Anchor.hpp)0
-rw-r--r--src/model/domain/ClassSet.hpp33
-rw-r--r--src/model/domain/Domain.hpp41
-rw-r--r--src/xml/XmlElementHandler.hpp146
-rw-r--r--src/xml/XmlReader.cpp99
-rw-r--r--src/xml/XmlReader.hpp78
-rw-r--r--test/model/GraphNode.cpp21
12 files changed, 463 insertions, 76 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8c9956a..26d695b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -54,19 +54,26 @@ INCLUDE_DIRECTORIES(
src/
)
-# ousia_core library (containing the code of the most important data structures
-# and deduction algorithms)
-ADD_LIBRARY(ousia_core
+# ousia_model library (containing the code of the most important data structures
+# and deduction algorithms -- this code does not depend on Qt).
+ADD_LIBRARY(ousia_model
src/model/GraphNode
- src/model/domain/Structure
- src/model/domain/Layer
- src/model/domain/Annotation
- src/model/domain/Anchor
- src/model/domain/Field
- src/model/types/Type
- src/model/types/Value
+ src/model/domain/Domain
)
+# ousia_xml library (containing the XML serialization/deserializing code for the
+# data structures defined in the ousia_model library)
+ADD_LIBRARY(ousia_xml
+ src/xml/XmlReader
+)
+
+TARGET_LINK_LIBRARIES(ousia_xml
+ ousia_model
+)
+
+# Link the ousia xml model against the core module of Qt5
+QT5_USE_MODULES(ousia_xml Core)
+
# Definition of the main program
ADD_EXECUTABLE(ousia
src/main
@@ -74,7 +81,8 @@ ADD_EXECUTABLE(ousia
# Link the ousia executable against ousia_core
TARGET_LINK_LIBRARIES(ousia
- ousia_core
+ ousia_model
+ ousia_xml
)
# Link the ousia executable against the Widgets module of Qt5
@@ -92,12 +100,12 @@ IF(test)
ADD_EXECUTABLE(ousia_test
test/model/RangeSet
test/model/GraphNode
- test/model/domain/Layer
)
TARGET_LINK_LIBRARIES(ousia_test
${GTEST_LIBRARIES}
- ousia_core
+ ousia_model
+ ousia_xml
)
# Register the unit test
diff --git a/src/main.cpp b/src/main.cpp
index 5c01bc3..6e3457c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,36 +6,31 @@
#include <vector>
#include <iostream>
-#include <model/GraphNode.hpp>
+#include <xml/XmlReader.hpp>
-using namespace ousia;
+using namespace ousia::xml;
int main(int argc, char *argv[])
{
- std::shared_ptr<GraphNode> nd1{new GraphNode("node1")};
- std::shared_ptr<GraphNode> nd2{new GraphNode("node2", nd1)};
-
- std::cout << nd2->getParent()->getName() << std::endl;
-
- return 0;
-
// Open the file given as first argument
-/* QFile file(argv[1]);
+ if (argc < 2) {
+ std::cout << "No filename specified!" << std::endl;
+ return 1;
+ }
+
+ QFile file(argv[1]);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
std::cout << "Error while opening file " << argv[1] << std::endl;
return 1;
}
- // Read all tags using the xml stream reader
+ // Create the QXmlStreamReader instance
QXmlStreamReader xml(&file);
- while (!xml.atEnd()) {
- xml.readNext();
- }
- if (xml.hasError()) {
- std::cout << "Error while parsing XML: " << xml.errorString().toStdString() << " at line " << xml.lineNumber() << std::endl;
- return 1;
- }
- return 0;*/
+ // Pass it to the XmlReader
+ XmlReader xmlReader(xml);
+ xmlReader.process();
+
+ return 0;
}
diff --git a/src/model/GraphNode.cpp b/src/model/GraphNode.cpp
index affc3af..bfb8e63 100644
--- a/src/model/GraphNode.cpp
+++ b/src/model/GraphNode.cpp
@@ -22,21 +22,11 @@
#include <sstream>
namespace ousia {
+namespace model {
-GraphNode::GraphNode() :
- parent(nullptr)
-{
- // Do nothing here
-}
-
-GraphNode::GraphNode(std::shared_ptr<GraphNode> parent) :
- parent(parent)
-{
- // Do nothing here
-}
-
-GraphNode::GraphNode(const std::string &name, std::shared_ptr<GraphNode> parent) :
- name(name), parent(parent)
+GraphNode::GraphNode(GraphNodeType type, std::shared_ptr<GraphNode> parent,
+ const std::string &name) :
+ type(type), parent(parent), name(name)
{
// Do nothing here
}
@@ -52,3 +42,5 @@ const std::string GraphNode::getFullyQualifiedName()
}
}
+}
+
diff --git a/src/model/GraphNode.hpp b/src/model/GraphNode.hpp
index 39770dd..8ce1a39 100644
--- a/src/model/GraphNode.hpp
+++ b/src/model/GraphNode.hpp
@@ -16,34 +16,39 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _GRAPH_NODE_HPP_
-#define _GRAPH_NODE_HPP_
+#ifndef _OUSIA_MODEL_GRAPH_NODE_HPP_
+#define _OUSIA_MODEL_GRAPH_NODE_HPP_
#include <string>
#include <memory>
namespace ousia {
+namespace model {
+
+enum class GraphNodeType {
+ None, Domain, Class, Annotation, Structure, ClassCategory,
+ AnnotationCategory
+};
class GraphNode {
private:
- std::string name;
+ GraphNodeType type;
std::shared_ptr<GraphNode> parent;
+ std::string name;
-public:
- GraphNode();
-
- GraphNode(std::shared_ptr<GraphNode> parent);
+protected:
+ GraphNode(GraphNodeType type, std::shared_ptr<GraphNode> parent = nullptr,
+ const std::string &name = "");
- GraphNode(const std::string &name, std::shared_ptr<GraphNode> parent = nullptr);
+public:
+ const std::string getFullyQualifiedName();
const std::string& getName()
{
return name;
}
- const std::string getFullyQualifiedName();
-
void setName(const std::string &name)
{
this->name = name;
@@ -51,7 +56,7 @@ public:
std::shared_ptr<GraphNode> getParent()
{
- return std::shared_ptr<GraphNode>(parent);
+ return parent;
}
void setParent(std::shared_ptr<GraphNode> parent)
@@ -59,10 +64,15 @@ public:
this->parent = parent;
}
+ GraphNodeType getType()
+ {
+ return type;
+ }
};
}
+}
-#endif /* _GRAPH_NODE_HPP_ */
+#endif /* _OUSIA_MODEL_GRAPH_NODE_HPP_ */
diff --git a/src/model/domain/Anchor.cpp b/src/model/document/Anchor.cpp
index e153161..e153161 100644
--- a/src/model/domain/Anchor.cpp
+++ b/src/model/document/Anchor.cpp
diff --git a/src/model/domain/Anchor.hpp b/src/model/document/Anchor.hpp
index 66ff8eb..66ff8eb 100644
--- a/src/model/domain/Anchor.hpp
+++ b/src/model/document/Anchor.hpp
diff --git a/src/model/domain/ClassSet.hpp b/src/model/domain/ClassSet.hpp
new file mode 100644
index 0000000..ebfe508
--- /dev/null
+++ b/src/model/domain/ClassSet.hpp
@@ -0,0 +1,33 @@
+/*
+ Ousía
+ Copyright (C) 2014 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+namespace ousia {
+namespace domain {
+
+#include "Class.hpp";
+
+class ClassSet {
+
+private:
+ std::vector<Class> classes;
+
+};
+
+}
+}
+
diff --git a/src/model/domain/Domain.hpp b/src/model/domain/Domain.hpp
index dd5ee4d..957ae4a 100644
--- a/src/model/domain/Domain.hpp
+++ b/src/model/domain/Domain.hpp
@@ -16,34 +16,42 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _DOMAIN_HPP_
-#define _DOMAIN_HPP_
+#ifndef _OUSIA_MODEL_DOMAIN_DOMAIN_HPP_
+#define _OUSIA_MODEL_DOMAIN_DOMAIN_HPP_
-#include <memory>
-#include <string>
-#include <vector>
+//#include <memory>
+//#include <string>
+//#include <vector>
#include <model/GraphNode.hpp>
-#include "Class.hpp"
-#include "Structure.hpp"
-#include "Category.hpp"
-#include "Layer.hpp"
+//#include "Class.hpp"
+//#include "Structure.hpp"
+//#include "Category.hpp"
+//#include "Layer.hpp"
namespace ousia {
+namespace model {
namespace domain {
class Domain : public GraphNode {
private:
- std::shared_ptr<Class> root;
- std::vector<std::shared_ptr<Structure>> structures;
- std::vector<std::shared_ptr<Category>> categories;
- std::vector<std::shared_ptr<Layer>> layers;
+// std::shared_ptr<Class> root;
+// std::vector<std::shared_ptr<Structure>> structures;
+// std::vector<std::shared_ptr<Category>> categories;
+// std::vector<std::shared_ptr<Layer>> layers;
public:
- std::shared_ptr<Class>& getRoot()
+ Domain(std::shared_ptr<GraphNode> parent = nullptr,
+ const std::string &name = "") :
+ GraphNode(GraphNodeType::Domain, parent, name)
+ {
+ // Do nothing here
+ }
+
+/* std::shared_ptr<Class>& getRoot()
{
return root;
}
@@ -61,12 +69,13 @@ public:
std::vector<std::shared_ptr<Layer>>& getLayers()
{
return layers;
- }
+ }*/
};
}
}
+}
-#endif /* _DOMAIN_HPP_ */
+#endif /* _OUSIA_MODEL_DOMAIN_DOMAIN_HPP_ */
diff --git a/src/xml/XmlElementHandler.hpp b/src/xml/XmlElementHandler.hpp
new file mode 100644
index 0000000..5d35b36
--- /dev/null
+++ b/src/xml/XmlElementHandler.hpp
@@ -0,0 +1,146 @@
+/*
+ Ousía
+ Copyright (C) 2014 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _OUSIA_XML_XML_ELEMENT_HANDLER_HPP_
+#define _OUSIA_XML_XML_ELEMENT_HANDLER_HPP_
+
+#include <functional>
+
+namespace ousia {
+namespace xml {
+
+/**
+ * Structure used internally for representing a function that is capable of
+ * handling a certain xml element tag.
+ */
+class XmlElementHandler {
+
+private:
+ /**
+ * Name of the XML element the handler is capable of handling.
+ */
+ const char *name;
+
+ /**
+ * Handler function.
+ */
+ std::function<bool()> handler;
+
+ /**
+ * Counter that can be used in order to realize elements that may only
+ * appear a certain number of times.
+ */
+ int count;
+
+ /**
+ * Contains the current count of matches. Contains the maximum count a
+ * certain element must appear. If -1 the element may appear a unlimited
+ * number of times.
+ */
+ int maxCount;
+
+ /**
+ * A certain other handler this one depends on (the other element must have
+ * appeared at least once in order for this handler to match). If set to
+ * nullptr no requirement relationship is established.
+ */
+ const XmlElementHandler *requiredElement;
+
+public:
+
+ /**
+ * Constructor of the XmlElementHandler structure.
+ */
+ XmlElementHandler(const char *name, const std::function<bool()> &handler,
+ int maxCount = -1, const XmlElementHandler *requiredElement = nullptr) :
+ name(name), handler(handler), count(0), maxCount(maxCount),
+ requiredElement(requiredElement)
+ {
+ // Do nothing here
+ }
+
+ /**
+ * Returns the name of the handler.
+ */
+ const char* getName() const
+ {
+ return name;
+ }
+
+ /**
+ * Returns true if this handler is currently valid.
+ */
+ bool valid() const
+ {
+ return ((maxCount < 0) || (count < maxCount))
+ && (!requiredElement || (requiredElement->count > 0));
+ }
+
+ /**
+ * Returns true if this handler matches the current state of the given
+ * QXmlStreamReader.
+ */
+ template<typename StrType>
+ bool matches(const StrType &tagName) const
+ {
+ return valid() && (tagName == name);
+ }
+
+ /**
+ * Executes the given handler.
+ */
+ bool execute()
+ {
+ count++;
+ return handler();
+ }
+
+ /**
+ * Function which assembles a string containing the names of the expected
+ * element types. Used for displaying error messages.
+ */
+ static std::string expectedElementsStr(const std::vector<XmlElementHandler> &handlers)
+ {
+ // Calculate a list of valid element handlers
+ std::vector<const XmlElementHandler*> validHandlers;
+ for (auto &h : handlers) {
+ if (h.valid()) {
+ validHandlers.push_back(&h);
+ }
+ }
+
+ // Assemble the string containing the list of expected elements
+ std::stringstream ss;
+ bool first = true;
+ for (auto &h : validHandlers) {
+ if (!first) {
+ ss << ", ";
+ }
+ ss << h->getName();
+ first = false;
+ }
+ return ss.str();
+ }
+
+};
+
+}
+}
+
+#endif /* _OUSIA_XML_XML_ELEMENT_HANDLER_HPP_ */
+
diff --git a/src/xml/XmlReader.cpp b/src/xml/XmlReader.cpp
new file mode 100644
index 0000000..fd03ffb
--- /dev/null
+++ b/src/xml/XmlReader.cpp
@@ -0,0 +1,99 @@
+/*
+ Ousía
+ Copyright (C) 2014 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <QXmlStreamReader>
+
+#include <sstream>
+#include <iostream>
+
+#include "XmlElementHandler.hpp"
+#include "XmlReader.hpp"
+
+namespace ousia {
+namespace xml {
+
+XmlReader::XmlReader(QXmlStreamReader &xml) :
+ xml(xml)
+{
+ // Do nothing here
+}
+
+bool XmlReader::expectOneOf(std::vector<XmlElementHandler> &handlers)
+{
+ // Skip all tokens except for "start element" and "end element"
+ while (!xml.atEnd()) {
+ // TODO: Implement mechanism for using the current state of the
+ // XmlStreamReader instead of always reading the next token?
+ const auto tokenType = xml.readNext();
+ switch (tokenType) {
+ case QXmlStreamReader::StartElement:
+ for (auto &h : handlers) {
+ if (h.matches(xml.name())) {
+ return h.execute();
+ }
+ }
+ // Expected tag was not found, display error message
+ // TODO: Use better logging mechanism!
+ std::cout << "Expected one of the following tags: ("
+ << XmlElementHandler::expectedElementsStr(handlers)
+ << "); but found element \""
+ << xml.name().toString().toStdString()
+ << "\" instead!" << std::endl;
+ return false;
+ case QXmlStreamReader::EndElement:
+ // Expected tag was not found, instead we found a closing tag!
+ // TODO: Use better logging mechanism!
+ std::cout << "Expected one of the following tags: ("
+ << XmlElementHandler::expectedElementsStr(handlers)
+ << "); but found end of element \""
+ << xml.name().toString().toStdString()
+ << "\" instead!" << std::endl;
+ return false;
+ default:
+ continue;
+ }
+ }
+ return false;
+}
+
+std::shared_ptr<model::GraphNode> XmlReader::process()
+{
+ std::shared_ptr<model::GraphNode> res{nullptr};
+ std::vector<XmlElementHandler> handlers{
+ {"domain", [&](){return (res = this->readDomain()) != nullptr;}}
+ };
+ if (!expectOneOf(handlers)) {
+ std::cout << "Errors occured while parsing XML file!" << std::endl;
+ return nullptr;
+ }
+ return res;
+}
+
+std::shared_ptr<model::domain::Domain> XmlReader::readDomain()
+{
+ if (!xml.attributes().hasAttribute("name")) {
+ std::cout << "Expected name attribute!" << std::endl;
+ return nullptr;
+ }
+ std::cout << "domain name: " << xml.attributes().value("name").toString().toStdString() << std::endl;
+ return std::shared_ptr<model::domain::Domain>(new model::domain::Domain());
+}
+
+}
+}
+
diff --git a/src/xml/XmlReader.hpp b/src/xml/XmlReader.hpp
new file mode 100644
index 0000000..d8f30a7
--- /dev/null
+++ b/src/xml/XmlReader.hpp
@@ -0,0 +1,78 @@
+/*
+ Ousía
+ Copyright (C) 2014 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _OUSIA_XML_XML_READER_HPP_
+#define _OUSIA_XML_XML_READER_HPP_
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include <model/GraphNode.hpp>
+#include <model/domain/Domain.hpp>
+
+class QXmlStreamReader;
+
+namespace ousia {
+namespace xml {
+
+class XmlElementHandler;
+
+/**
+ * The XmlReader class is responsible for parsing the ousia XML documents and
+ * deserializing them into the internal object representation.
+ */
+class XmlReader {
+
+private:
+ /**
+ * Reference to the QXmlStreamReader used for accessing the XML data on a
+ * token basis.
+ */
+ QXmlStreamReader &xml;
+
+ /**
+ * Parses a domain definition from the XML file.
+ */
+ std::shared_ptr<model::domain::Domain> readDomain();
+
+ /**
+ * Used internally in order to conveniently expect one of a set of elements.
+ */
+ bool expectOneOf(std::vector<XmlElementHandler> &handlers);
+
+public:
+
+ /**
+ * Instanciates the XMLReader class for the given instance of the
+ * QXMLStreamReader class.
+ */
+ XmlReader(QXmlStreamReader &xml);
+
+ /**
+ * Starts processing the xml and returns the generated graph node.
+ */
+ std::shared_ptr<model::GraphNode> process();
+
+};
+
+}
+}
+
+#endif /* _OUSIA_XML_XML_READER_HPP_ */
+
diff --git a/test/model/GraphNode.cpp b/test/model/GraphNode.cpp
index a5596f5..7f6f2f9 100644
--- a/test/model/GraphNode.cpp
+++ b/test/model/GraphNode.cpp
@@ -21,14 +21,31 @@
#include <model/GraphNode.hpp>
namespace ousia {
+namespace model {
+
+// Make the protected constructor of GraphNode available
+class TestGraphNode : public GraphNode {
+
+public:
+ TestGraphNode(GraphNodeType type, std::shared_ptr<GraphNode> parent,
+ const std::string &name) :
+ GraphNode(type, parent, name)
+ {
+ // Do nothing here
+ }
+
+};
TEST(GraphNodeTest, FullyQuallifiedNameTest)
{
- std::shared_ptr<GraphNode> nd1{new GraphNode("node1")};
- std::shared_ptr<GraphNode> nd2{new GraphNode("node2", nd1)};
+ std::shared_ptr<GraphNode> nd1{new TestGraphNode(
+ GraphNodeType::None, nullptr, "node1")};
+ std::shared_ptr<GraphNode> nd2{new TestGraphNode(
+ GraphNodeType::None, nd1, "node2")};
ASSERT_STREQ("node1.node2", nd2->getFullyQualifiedName().c_str());
}
}
+}