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/main.cpp | 33 ++++------ src/model/GraphNode.cpp | 20 ++---- src/model/GraphNode.hpp | 34 ++++++---- src/model/document/Anchor.cpp | 28 ++++++++ src/model/document/Anchor.hpp | 36 +++++++++++ src/model/domain/Anchor.cpp | 28 -------- src/model/domain/Anchor.hpp | 36 ----------- src/model/domain/ClassSet.hpp | 33 ++++++++++ src/model/domain/Domain.hpp | 41 +++++++----- src/xml/XmlElementHandler.hpp | 146 ++++++++++++++++++++++++++++++++++++++++++ src/xml/XmlReader.cpp | 99 ++++++++++++++++++++++++++++ src/xml/XmlReader.hpp | 78 ++++++++++++++++++++++ 12 files changed, 487 insertions(+), 125 deletions(-) create mode 100644 src/model/document/Anchor.cpp create mode 100644 src/model/document/Anchor.hpp delete mode 100644 src/model/domain/Anchor.cpp delete mode 100644 src/model/domain/Anchor.hpp create mode 100644 src/model/domain/ClassSet.hpp create mode 100644 src/xml/XmlElementHandler.hpp create mode 100644 src/xml/XmlReader.cpp create mode 100644 src/xml/XmlReader.hpp (limited to 'src') 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 #include -#include +#include -using namespace ousia; +using namespace ousia::xml; int main(int argc, char *argv[]) { - std::shared_ptr nd1{new GraphNode("node1")}; - std::shared_ptr 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 namespace ousia { +namespace model { -GraphNode::GraphNode() : - parent(nullptr) -{ - // Do nothing here -} - -GraphNode::GraphNode(std::shared_ptr parent) : - parent(parent) -{ - // Do nothing here -} - -GraphNode::GraphNode(const std::string &name, std::shared_ptr parent) : - name(name), parent(parent) +GraphNode::GraphNode(GraphNodeType type, std::shared_ptr 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 . */ -#ifndef _GRAPH_NODE_HPP_ -#define _GRAPH_NODE_HPP_ +#ifndef _OUSIA_MODEL_GRAPH_NODE_HPP_ +#define _OUSIA_MODEL_GRAPH_NODE_HPP_ #include #include 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 parent; + std::string name; -public: - GraphNode(); - - GraphNode(std::shared_ptr parent); +protected: + GraphNode(GraphNodeType type, std::shared_ptr parent = nullptr, + const std::string &name = ""); - GraphNode(const std::string &name, std::shared_ptr 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 getParent() { - return std::shared_ptr(parent); + return parent; } void setParent(std::shared_ptr 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/document/Anchor.cpp b/src/model/document/Anchor.cpp new file mode 100644 index 0000000..e153161 --- /dev/null +++ b/src/model/document/Anchor.cpp @@ -0,0 +1,28 @@ +/* + 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 + +namespace ousia { +namespace domain { + +//This class is fully specified by its header. + +} +} + diff --git a/src/model/document/Anchor.hpp b/src/model/document/Anchor.hpp new file mode 100644 index 0000000..66ff8eb --- /dev/null +++ b/src/model/document/Anchor.hpp @@ -0,0 +1,36 @@ +/* + 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 _ANCHOR_HPP_ +#define _ANCHOR_HPP_ + +#include + +namespace ousia { +namespace domain { + +class Anchor : public GraphNode { + +public: + using GraphNode::GraphNode; + +}; +} +} + +#endif /* _ANCHOR_HPP_ */ diff --git a/src/model/domain/Anchor.cpp b/src/model/domain/Anchor.cpp deleted file mode 100644 index e153161..0000000 --- a/src/model/domain/Anchor.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - 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 - -namespace ousia { -namespace domain { - -//This class is fully specified by its header. - -} -} - diff --git a/src/model/domain/Anchor.hpp b/src/model/domain/Anchor.hpp deleted file mode 100644 index 66ff8eb..0000000 --- a/src/model/domain/Anchor.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - 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 _ANCHOR_HPP_ -#define _ANCHOR_HPP_ - -#include - -namespace ousia { -namespace domain { - -class Anchor : public GraphNode { - -public: - using GraphNode::GraphNode; - -}; -} -} - -#endif /* _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 . +*/ + +namespace ousia { +namespace domain { + +#include "Class.hpp"; + +class ClassSet { + +private: + std::vector 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 . */ -#ifndef _DOMAIN_HPP_ -#define _DOMAIN_HPP_ +#ifndef _OUSIA_MODEL_DOMAIN_DOMAIN_HPP_ +#define _OUSIA_MODEL_DOMAIN_DOMAIN_HPP_ -#include -#include -#include +//#include +//#include +//#include #include -#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 root; - std::vector> structures; - std::vector> categories; - std::vector> layers; +// std::shared_ptr root; +// std::vector> structures; +// std::vector> categories; +// std::vector> layers; public: - std::shared_ptr& getRoot() + Domain(std::shared_ptr parent = nullptr, + const std::string &name = "") : + GraphNode(GraphNodeType::Domain, parent, name) + { + // Do nothing here + } + +/* std::shared_ptr& getRoot() { return root; } @@ -61,12 +69,13 @@ public: std::vector>& 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 . +*/ + +#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