From d99095f4a181357bf0c6d10846351eb0b58b1ccf Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Thu, 6 Mar 2014 00:11:17 +0000 Subject: 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 --- src/xml/XmlElementHandler.hpp | 146 ++++++++++++++++++++++++++++++++++++++++++ src/xml/XmlReader.cpp | 99 ++++++++++++++++++++++++++++ src/xml/XmlReader.hpp | 78 ++++++++++++++++++++++ 3 files changed, 323 insertions(+) create mode 100644 src/xml/XmlElementHandler.hpp create mode 100644 src/xml/XmlReader.cpp create mode 100644 src/xml/XmlReader.hpp (limited to 'src/xml') 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 . +*/ + +#ifndef _OUSIA_XML_XML_ELEMENT_HANDLER_HPP_ +#define _OUSIA_XML_XML_ELEMENT_HANDLER_HPP_ + +#include + +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 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 &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 + 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 &handlers) + { + // Calculate a list of valid element handlers + std::vector 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 . +*/ + +#include + +#include +#include + +#include "XmlElementHandler.hpp" +#include "XmlReader.hpp" + +namespace ousia { +namespace xml { + +XmlReader::XmlReader(QXmlStreamReader &xml) : + xml(xml) +{ + // Do nothing here +} + +bool XmlReader::expectOneOf(std::vector &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 XmlReader::process() +{ + std::shared_ptr res{nullptr}; + std::vector 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 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(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 . +*/ + +#ifndef _OUSIA_XML_XML_READER_HPP_ +#define _OUSIA_XML_XML_READER_HPP_ + +#include +#include +#include + +#include +#include + +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 readDomain(); + + /** + * Used internally in order to conveniently expect one of a set of elements. + */ + bool expectOneOf(std::vector &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 process(); + +}; + +} +} + +#endif /* _OUSIA_XML_XML_READER_HPP_ */ + -- cgit v1.2.3