diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cpp | 33 | ||||
-rw-r--r-- | src/model/GraphNode.cpp | 20 | ||||
-rw-r--r-- | src/model/GraphNode.hpp | 34 | ||||
-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.hpp | 33 | ||||
-rw-r--r-- | src/model/domain/Domain.hpp | 41 | ||||
-rw-r--r-- | src/xml/XmlElementHandler.hpp | 146 | ||||
-rw-r--r-- | src/xml/XmlReader.cpp | 99 | ||||
-rw-r--r-- | src/xml/XmlReader.hpp | 78 |
10 files changed, 423 insertions, 61 deletions
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_ */ + |