diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2014-03-06 11:50:53 +0000 |
---|---|---|
committer | andreas <andreas@daaaf23c-2e50-4459-9457-1e69db5a47bf> | 2014-03-06 11:50:53 +0000 |
commit | 247945811adbfb5ddaa1ba4e1f3dfc20cd7eb058 (patch) | |
tree | cad76062be455d4324d03f5ce38c9b599f6b7e25 | |
parent | 36a1402be747136711edc19f7bce45f36a625eb4 (diff) |
added attribute handler
git-svn-id: file:///var/local/svn/basicwriter@28 daaaf23c-2e50-4459-9457-1e69db5a47bf
-rw-r--r-- | src/xml/XmlAttributeHandler.hpp | 138 | ||||
-rw-r--r-- | src/xml/XmlReader.cpp | 49 | ||||
-rw-r--r-- | src/xml/XmlReader.hpp | 13 |
3 files changed, 197 insertions, 3 deletions
diff --git a/src/xml/XmlAttributeHandler.hpp b/src/xml/XmlAttributeHandler.hpp new file mode 100644 index 0000000..8fae6c3 --- /dev/null +++ b/src/xml/XmlAttributeHandler.hpp @@ -0,0 +1,138 @@ +/* + 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_ATTRIBUTE_HANDLER_HPP_ +#define _OUSIA_XML_XML_ATTRIBUTE_HANDLER_HPP_ + +#include <functional> +#include <string> + +namespace ousia { +namespace xml { + +/** + * The attribute handler class is responsible for handling attributes. It + * performs type checks and conversion. Note that the name of the attribute is + * not stored inside the handler, as the attribute handlers are meant to be used + * alongside a map. + */ +class XmlAttributeHandler { + +private: + /** + * Specifies whether this attribute was actually handled (set to true once + * the setter is called). + */ + bool handled; + + /** + * Specifies whether this attribute is required or not. + */ + bool required; + + /** + * Function which returns true if the given string is a valid entry for the + * type the attribute handler represents. + */ + std::function<bool(const std::string&)> valid; + + /** + * Function which gets the attribute value and sets the type. + */ + std::function<void(const std::string&)> setter; + + /** + * Default value (as string) that should be used if no other value for that + * attribute is given. + */ + const char *defaultValue; + +public: + + /** + * Constructor of the XmlAttributeHandler class. + * + * @param required if true, the attribute is marked as "required" and it + * must occur in the xml. + * @param valid is a function reference which specifies whether the given + * string is valid. + * @param setter is the function that is meant to actually set the value + * of the attached class. + * @param defaultValue if given (it does not equal the nullptr), the setter + * is automatically called with the default value, unless the attribute is + * actually specified in the XML. + */ + XmlAttributeHandler(bool required, + const std::function<bool(const std::string&)> &valid, + const std::function<void(const std::string&)> &setter, + const char *defaultValue = nullptr) : + handled(false), required(required), valid(valid), setter(setter), + defaultValue(defaultValue) + { + // Do nothing here + } + + /** + * Returns true if the given value for this attribute is valid. + */ + bool isValid(const std::string &value) + { + return valid(value); + } + + /** + * Calls the setter with the given value. The value should have been checked + * for validity first. + */ + void executeSettter(const std::string &value) + { + handled = true; + setter(value); + } + + /** + * Returns true if this element is required. + */ + bool isRequired() + { + return required; + } + + /** + * Returns the default value. + */ + const char* getDefaultValue() + { + return defaultValue; + } + + /** + * Returns true if the attribute was handled. + */ + bool isHandled() + { + return handled; + } + +}; + +} +} + +#endif /* _OUSIA_XML_XML_ATTRIBUTE_HANDLER_HPP_ */ + diff --git a/src/xml/XmlReader.cpp b/src/xml/XmlReader.cpp index c7de564..95f326c 100644 --- a/src/xml/XmlReader.cpp +++ b/src/xml/XmlReader.cpp @@ -18,9 +18,11 @@ #include <QXmlStreamReader> -#include <sstream> +#include <functional> #include <iostream> +#include <sstream> +#include "XmlAttributeHandler.hpp" #include "XmlElementHandler.hpp" #include "XmlReader.hpp" @@ -72,6 +74,51 @@ bool XmlReader::expectOneOf(std::vector<XmlElementHandler> &handlers) return false; } +bool XmlReader::parseArguments(std::map<std::string, XmlAttributeHandler> &handlers) +{ + // Iterate the attributes of the current xml node + for (auto &attr : xml.attributes()) { + // Convert the name to a std string + const std::string name = attr.name().toString().toStdString(); + const std::string value = attr.value().toString().toStdString(); + + // Try to fetch a corresponding attribute in the handlers map + auto it = handlers.find(name); + if (it != handlers.end()) { + XmlAttributeHandler &handler = (*it).second; + if (handler.isValid(value)) { + handler.executeSettter(value); + } else { + std::cout << "Invalid attribute value \"" << value + << "\" for attribute " << name << std::endl; + return false; + } + } else { + std::cout << "Unexpected attribute " << name << std::endl; + return false; + } + } + + // Iterate over all handlers to check whether all required handlers have + // been handled and in order to pass the default value to unhandled handlers + for (auto &it : handlers) { + // Fetch the name of the attribute and the handler + const std::string &name = it.first; + XmlAttributeHandler &handler = it.second; + if (!handler.isHandled()) { + if (handler.isRequired()) { + std::cout << "Attribute " << name + << " is required but was not set!" << std::endl; + return false; + } else if (handler.getDefaultValue()) { + handler.executeSettter(handler.getDefaultValue()); + } + } + } + + return true; +} + std::shared_ptr<model::GraphNode> XmlReader::process() { std::shared_ptr<model::GraphNode> res{nullptr}; diff --git a/src/xml/XmlReader.hpp b/src/xml/XmlReader.hpp index d8f30a7..f9b949b 100644 --- a/src/xml/XmlReader.hpp +++ b/src/xml/XmlReader.hpp @@ -19,8 +19,9 @@ #ifndef _OUSIA_XML_XML_READER_HPP_ #define _OUSIA_XML_XML_READER_HPP_ -#include <functional> +#include <map> #include <memory> +#include <string> #include <vector> #include <model/GraphNode.hpp> @@ -32,6 +33,7 @@ namespace ousia { namespace xml { class XmlElementHandler; +class XmlAttributeHandler; /** * The XmlReader class is responsible for parsing the ousia XML documents and @@ -52,10 +54,17 @@ private: std::shared_ptr<model::domain::Domain> readDomain(); /** - * Used internally in order to conveniently expect one of a set of elements. + * Used internally in order to conveniently expect one xml tag in a set of + * elements. Returns true if there was an error while waiting for the tag, + * false otherwise. */ bool expectOneOf(std::vector<XmlElementHandler> &handlers); + /** + * Used internally to parse the current argument map. + */ + bool parseArguments(std::map<std::string, XmlAttributeHandler> &handlers); + public: /** |