diff options
Diffstat (limited to 'src/xml')
-rw-r--r-- | src/xml/XmlElementHandler.hpp | 146 | ||||
-rw-r--r-- | src/xml/XmlReader.cpp | 99 | ||||
-rw-r--r-- | src/xml/XmlReader.hpp | 78 |
3 files changed, 323 insertions, 0 deletions
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_ */ + |