/* Ousía Copyright (C) 2014, 2015 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 . */ /** * @file Argument.hpp * * Contains the declaration of the Argument and Arguments classes which are used * to define the list of Arguments that can be passed to a Method or the set * of attributes that are attached to an XML node or similar. * * The Argument and Arguments classes have some ressemblance to the Attribute * and StructType types, however the classes defined here have been built to * represent types which are known at compile time, whereas Attribute and * StructType represent types defined at runtime by the user. * * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de) */ #ifndef _OUSIA_ARGUMENT_HPP_ #define _OUSIA_ARGUMENT_HPP_ #include #include #include #include "Variant.hpp" namespace ousia { // Forward declaration class Logger; class Rtti; /** * The Argument class represents a single argument that can be passed to a * function. */ class Argument { private: /** * Contains the name of the argument. Used for logging and in case the * arguments are presented as map. */ std::string name; /** * Type that should be returned by the Variant rttiType function. */ Rtti const* type; /** * Describes the inner type of the variant -- e.g. the type of the elements * inside an array. Normally set to RttiTypes::None. */ Rtti const* innerType; /** * Default value. Note that a value of nullptr does not indicate that no * default value has been set. Use the "hasDefault" flag for this purpose. * Nullptr is a valid value for objects. */ Variant defaultValue; /** * True if a default value is set, false otherwise. */ bool hasDefaultValue; /** * Private constructor used for manually setting all internal data fields. * * @param name is the name of the Argument. * @param variantType is the variant type of the argument that is to be * expected. * @param rttiType is the rttiType of the argument. Only used it the type * of the variant is an object. * @param defaultValue is the default value to be used. * @param hasDefault indicates whether the defaultValue actually should be * used. */ Argument(std::string name, const Rtti &type, const Rtti &innerType, Variant defaultValue, bool hasDefault); /** * Private constructor used to build an argument describing a primitive type * with default value. * * @param name is the name of the Argument. * @param variantType is the variant type of the argument that is to be * expected. * @param defaultValue is the default value to be used. */ Argument(std::string name, const Rtti &type, Variant defaultValue); /** * Private constructor used to build an argument describing a primitive type * without default value. * * @param name is the name of the Argument. * @param variantType is the variant type of the argument that is to be * expected. */ Argument(std::string name, const Rtti &type); public: /** * Named constructor for an argument with any type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @return a new Argument instance. */ static Argument Any(std::string name); /** * Named constructor for an argument with any type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument Any(std::string name, Variant defaultValue); /** * Named constructor for a boolean argument with no default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @return a new Argument instance. */ static Argument Bool(std::string name); /** * Named constructor for a boolean argument with default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument Bool(std::string name, Variant::boolType defaultValue); /** * Named constructor for an integer argument with no default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @return a new Argument instance. */ static Argument Int(std::string name); /** * Named constructor for an integer argument with default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument Int(std::string name, Variant::intType defaultValue); /** * Named constructor for a double argument with no default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @return a new Argument instance. */ static Argument Double(std::string name); /** * Named constructor for a double argument with default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument Double(std::string name, Variant::doubleType defaultValue); /** * Named constructor for a string argument with no default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @return a new Argument instance. */ static Argument String(std::string name); /** * Named constructor for a string argument with default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument String(std::string name, const Variant::stringType &defaultValue); /** * Named constructor for an object argument with no default value. Object * arguments always point at an instance of the Managed class. The concrete * Object type must be specified in the "type" argument. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param type is the Rtti of acceptable objects. All objects where the * "isa" function returns true for the given type are be accepted. * @return a new Argument instance. */ static Argument Object(std::string name, const Rtti &type); /** * Named constructor for an object argument with default value. The default * value can only be nullptr. Object arguments always point at an instance * of the Managed class. The concrete Object type must be specified in the * "type" argument. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param type is the Rtti of acceptable objects. All objects where the * "isa" function returns true for the given type are be accepted. * @param defaultValue must be set to nullptr. Default object instances * cannot be stored. * @return a new Argument instance. */ static Argument Object(std::string name, const Rtti &type, std::nullptr_t defaultValue); /** * Named constructor for a function argument with no default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @return a new Argument instance. */ static Argument Function(std::string name); /** * Named constructor for a function argument with default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument Function(std::string name, Variant::functionType defaultValue); /** * Named constructor for an integer argument with no default and no specific * inner type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @return a new Argument instance. */ static Argument Array(std::string name); /** * Named constructor for an array argument with default value and no * specific inner type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument Array(std::string name, const Variant::arrayType &defaultValue); /** * Named constructor for an array argument of objects of the given RTTI * type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param innerType is the inner type of the array. All array elements are * forced to be of this type. * @return a new Argument instance. */ static Argument Array(std::string name, const Rtti &innerType); /** * Named constructor for an array argument of objects of the given RTTI * type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param innerType is the inner type of the array. All array elements are * forced to be of this type. * @return a new Argument instance. * @param defaultValue is the default value to be used in case this argument * is not supplied. */ static Argument Array(std::string name, const Rtti &innerType, const Variant::arrayType &defaultValue); /** * Named constructor for a map argument with no default value and no * specific inner type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @return a new Argument instance. */ static Argument Map(std::string name); /** * Named constructor for a map argument with default value and no specific * inner type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument Map(std::string name, const Variant::mapType &defaultValue); /** * Named constructor for a map argument with no default value and a given * inner type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param innerType is the inner type of the map. All map entries are forced * to be of this type. * @return a new Argument instance. */ static Argument Map(std::string name, const Rtti &innerType); /** * Named constructor for a map argument with default value and a given inner * type. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param innerType is the inner type of the map. All map entries are forced * to be of this type. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument Map(std::string name, const Rtti &innerType, const Variant::mapType &defaultValue); /** * Named constructor for a cardinality argument with no default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @return a new Argument instance. */ static Argument Cardinality(std::string name); /** * Named constructor for a Cardinality argument with default value. * * @param name is the name of the argument as used for error messages and in * case the arguments are given as a map. * @param defaultValue is the default value to be used in case this argument * is not supplied. * @return a new Argument instance. */ static Argument Cardinality(std::string name, Variant::cardinalityType defaultValue); /** * Makes sure the given variant is in the requested format and returns true * if the variant was valid. Logs any error to the given logger instance. * In case the validation was not successful, but the Argument instance was * given an default value, the variant is set to that default value. If no * default value was given, the variant is set to a valid value of the * requested type. * * @param var is the variant that should be verified and transformed to * match the argument specification. * @param logger is the logger instance to which errors should be written. * @return true if the given variant was valid, false otherwise. */ bool validate(Variant &var, Logger &logger) const; /** * Returns the name of the argument. The name is used for logging and in * case a map is presented as arguments. * * @return the name of the argument given in the constructor. */ const std::string &getName() const; /** * Returns the default value. Note that a value of nullptr does not indicate * that no default value has been set. Use the "hasDefault" flag for this * purpose. Nullptr is a valid value for objects. * * @return the default value that was given in the constructor (may be * nullptr) and nullptr if no default value was given. */ const Variant& getDefaultValue() const; /** * Returns true if a default value was set in the constructor. * * @return true if a default value is set, false otherwise. */ bool hasDefault() const; }; /** * The Arguments class represents a list of Argument instances and allows to * either compare an array or a map of Variant instances against this argument * list. */ class Arguments { private: /** * List storing all arguments this instance consists of. */ std::vector arguments; /** * Map containing all used argument names. */ std::unordered_map names; /** * Set to true if arguments were explicitly given in the constructor, * false otherwise. */ bool valid; public: /** * Static Arguments instance with no explicit arguments set. */ static const Arguments None; /** * Default constructor. Provides no arguments. */ Arguments() : valid(false){}; /** * Constructor of the Arguments class from a list of Argument instances. * * @param arguments is a list of Argument instances with which the Arguments * instance should be initialized. */ Arguments(std::initializer_list arguments); /** * Checks whether the content of the given variant array matches the * argument list stored in this Arguments instance. Any ommited default * arguments are added to the array. * * @param arr is the variant array that should be validated. The array is * extended by all missing default values. The resulting array is ensured to * be of the correct length and all entries to be of the correct type, even * if validation errors occured (to facilitate graceful degradation). * @param logger is the logger instance to which error messages or warnings * will be written. * @return true if the operation was successful, false if an error occured. */ bool validateArray(Variant::arrayType &arr, Logger &logger) const; /** * Checks whether the content of the given variant map matches the * argument list stored in this Arguments instance. Any ommited default * arguments are added to the map. * * @param map is the variant map that should be validated. The map is * extended by all missing default values. The resulting map is ensured to * be of the correct length and all entries to be of the correct type, even * if validation errors occured (to facilitate graceful degradation). * @param logger is the logger instance to which error messages or warnings * will be written. * @param ignoreUnknown if set to true, unknown map entries are ignored * (a note is issued). This behaviour can be usefull if forward * compatibility must be achieved (such as for XML based formats). * @return true if the operation was successful, false if an error occured. */ bool validateMap(Variant::mapType &map, Logger &logger, bool ignoreUnknown = false) const; }; } #endif /* _OUSIA_ARGUMENT_HPP_ */