You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

259 lines
12 KiB

#ifndef STORM_SETTINGS_ARGUMENTBUILDER_H_
#define STORM_SETTINGS_ARGUMENTBUILDER_H_
#include <iostream>
#include <sstream>
#include <list>
#include <utility>
#include <functional>
#include <unordered_map>
#include <vector>
#include <memory>
#include <string>
#include "ArgumentType.h"
#include "ArgumentTypeInferationHelper.h"
#include "ArgumentBase.h"
#include "Argument.h"
#include "ArgumentValidators.h"
#include "src/exceptions/IllegalFunctionCallException.h"
#include "src/exceptions/IllegalArgumentTypeException.h"
#include "log4cplus/logger.h"
#include "log4cplus/loggingmacros.h"
extern log4cplus::Logger logger;
namespace storm {
namespace settings {
class ArgumentBuilder {
public:
~ArgumentBuilder() {}
/*
Preparation Functions for all ArgumentType's
Resets all internal attributes
*/
static ArgumentBuilder createStringArgument(std::string const& argumentName, std::string const& argumentDescription) {
ArgumentBuilder ab(ArgumentType::String, argumentName, argumentDescription);
return ab;
}
static ArgumentBuilder createIntegerArgument(std::string const& argumentName, std::string const& argumentDescription) {
ArgumentBuilder ab(ArgumentType::Integer, argumentName, argumentDescription);
return ab;
}
static ArgumentBuilder createUnsignedIntegerArgument(std::string const& argumentName, std::string const& argumentDescription) {
ArgumentBuilder ab(ArgumentType::UnsignedInteger, argumentName, argumentDescription);
return ab;
}
static ArgumentBuilder createDoubleArgument(std::string const& argumentName, std::string const& argumentDescription) {
ArgumentBuilder ab(ArgumentType::Double, argumentName, argumentDescription);
return ab;
}
static ArgumentBuilder createBooleanArgument(std::string const& argumentName, std::string const& argumentDescription) {
ArgumentBuilder ab(ArgumentType::Boolean, argumentName, argumentDescription);
return ab;
}
ArgumentBuilder& setName(std::string const& newName) {
this->argumentName = newName;
return *this;
}
ArgumentBuilder& setDescription(std::string const& newDescription) {
this->argumentDescription = newDescription;
return *this;
}
ArgumentBuilder& setIsOptional(bool isOptional) {
this->isOptional = isOptional;
return *this;
}
#define PPCAT_NX(A, B) A ## B
#define PPCAT(A, B) PPCAT_NX(A, B)
#define MACROaddValidationFunction(funcName, funcType) ArgumentBuilder& PPCAT(addValidationFunction, funcName) (storm::settings::Argument< funcType >::userValidationFunction_t userValidationFunction) { \
if (this->argumentType != ArgumentType::funcName) { \
throw storm::exceptions::IllegalFunctionCallException() << "Tried adding a Validation-Function for a \"" << ArgumentTypeHelper::toString(ArgumentType::funcName) << "\" Argument, but this Argument is configured to be of Type \"" << ArgumentTypeHelper::toString(this->argumentType) << "\"."; \
} \
( PPCAT(this->userValidationFunction_, funcName) ).push_back(userValidationFunction); \
std::string errorMessageTarget = ""; \
if (this->hasDefaultValue && !this->validateDefaultForEach(errorMessageTarget)) { \
throw storm::exceptions::IllegalArgumentValueException() << "Tried adding a Validation-Function for an Argument which has a Default Value set which is rejected by this Validation-Function:\r\n" << errorMessageTarget; \
} \
return *this; \
}
MACROaddValidationFunction(String, std::string)
MACROaddValidationFunction(Integer, int_fast64_t)
MACROaddValidationFunction(UnsignedInteger, uint_fast64_t)
MACROaddValidationFunction(Double, double)
MACROaddValidationFunction(Boolean, bool)
#define MACROsetDefaultValue(funcName, funcType) ArgumentBuilder& PPCAT(setDefaultValue, funcName) (funcType const& defaultValue) { \
if (this->argumentType != ArgumentType::funcName) { \
throw storm::exceptions::IllegalFunctionCallException() << "Tried adding a default Value for a \"" << ArgumentTypeHelper::toString(ArgumentType::String) << "\" Argument, but the Argument \"" << this->argumentName << "\" is configured to be of Type \"" << ArgumentTypeHelper::toString(this->argumentType) << "\"."; \
} \
PPCAT(this->defaultValue_, funcName) = defaultValue; \
std::string errorMessageTarget = ""; \
if (!this->validateDefaultForEach(errorMessageTarget)) { \
throw storm::exceptions::IllegalArgumentValueException() << "Tried adding a default Value for the Argument \"" << this->argumentName << "\", but a Validation Function rejected it:\r\n" << errorMessageTarget; \
} \
this->hasDefaultValue = true; \
return *this; \
}
MACROsetDefaultValue(String, std::string)
MACROsetDefaultValue(Integer, int_fast64_t)
MACROsetDefaultValue(UnsignedInteger, uint_fast64_t)
MACROsetDefaultValue(Double, double)
MACROsetDefaultValue(Boolean, bool)
ArgumentBase* build() {
if (this->hasBeenBuild) {
throw storm::exceptions::IllegalFunctionCallException() << "Called build() on an instance of ArgumentBuilder which has already build an Instance.";
}
this->hasBeenBuild = true;
switch (this->argumentType) {
case ArgumentType::String: {
if (this->hasDefaultValue) {
return dynamic_cast<ArgumentBase*>(new Argument<std::string>(this->argumentName, this->argumentDescription, userValidationFunction_String, this->isOptional, this->defaultValue_String));
} else {
return dynamic_cast<ArgumentBase*>(new Argument<std::string>(this->argumentName, this->argumentDescription, userValidationFunction_String, this->isOptional));
}
break;
}
case ArgumentType::Integer:
if (this->hasDefaultValue) {
return dynamic_cast<ArgumentBase*>(new Argument<int_fast64_t>(this->argumentName, this->argumentDescription, userValidationFunction_Integer, this->isOptional, this->defaultValue_Integer));
} else {
return dynamic_cast<ArgumentBase*>(new Argument<int_fast64_t>(this->argumentName, this->argumentDescription, userValidationFunction_Integer, this->isOptional));
}
break;
case ArgumentType::UnsignedInteger:
if (this->hasDefaultValue) {
return dynamic_cast<ArgumentBase*>(new Argument<uint_fast64_t>(this->argumentName, this->argumentDescription, userValidationFunction_UnsignedInteger, this->isOptional, this->defaultValue_UnsignedInteger));
} else {
return dynamic_cast<ArgumentBase*>(new Argument<uint_fast64_t>(this->argumentName, this->argumentDescription, userValidationFunction_UnsignedInteger, this->isOptional));
}
break;
case ArgumentType::Double:
if (this->hasDefaultValue) {
return dynamic_cast<ArgumentBase*>(new Argument<double>(this->argumentName, this->argumentDescription, userValidationFunction_Double, this->isOptional, this->defaultValue_Double));
} else {
return dynamic_cast<ArgumentBase*>(new Argument<double>(this->argumentName, this->argumentDescription, userValidationFunction_Double, this->isOptional));
}
break;
case ArgumentType::Boolean:
if (this->hasDefaultValue) {
return dynamic_cast<ArgumentBase*>(new Argument<bool>(this->argumentName, this->argumentDescription, userValidationFunction_Boolean, this->isOptional, this->defaultValue_Boolean));
} else {
return dynamic_cast<ArgumentBase*>(new Argument<bool>(this->argumentName, this->argumentDescription, userValidationFunction_Boolean, this->isOptional));
}
break;
default: {
throw storm::exceptions::InternalTypeErrorException() << "Missing Case in ArgumentBuilder's switch/case Code.";
}
}
}
private:
ArgumentBuilder(ArgumentType argumentType, std::string const& argumentName, std::string const& argumentDescription) : hasBeenBuild(false), argumentType(argumentType), argumentName(argumentName), argumentDescription(argumentDescription), isOptional(false), hasDefaultValue(false) {
//
}
ArgumentBuilder(ArgumentBuilder& other) : hasBeenBuild(other.hasBeenBuild), argumentType(other.argumentType), argumentName(other.argumentName), argumentDescription(other.argumentDescription), isOptional(other.isOptional),
defaultValue_String(other.defaultValue_String), defaultValue_Integer(other.defaultValue_Integer), defaultValue_UnsignedInteger(other.defaultValue_UnsignedInteger), defaultValue_Double(other.defaultValue_Double), defaultValue_Boolean(other.defaultValue_Boolean),
hasDefaultValue(other.hasDefaultValue) {
// Copy all userFunctions
for (uint_fast64_t i = 0; i < userValidationFunction_String.size(); ++i) {
this->userValidationFunction_String.push_back(storm::settings::Argument<std::string>::userValidationFunction_t(other.userValidationFunction_String.at(i)));
}
for (uint_fast64_t i = 0; i < userValidationFunction_Integer.size(); ++i) {
this->userValidationFunction_Integer.push_back(storm::settings::Argument<int_fast64_t>::userValidationFunction_t(other.userValidationFunction_Integer.at(i)));
}
for (uint_fast64_t i = 0; i < userValidationFunction_UnsignedInteger.size(); ++i) {
this->userValidationFunction_UnsignedInteger.push_back(storm::settings::Argument<uint_fast64_t>::userValidationFunction_t(other.userValidationFunction_UnsignedInteger.at(i)));
}
for (uint_fast64_t i = 0; i < userValidationFunction_Double.size(); ++i) {
this->userValidationFunction_Double.push_back(storm::settings::Argument<double>::userValidationFunction_t(other.userValidationFunction_Double.at(i)));
}
for (uint_fast64_t i = 0; i < userValidationFunction_Boolean.size(); ++i) {
this->userValidationFunction_Boolean.push_back(storm::settings::Argument<bool>::userValidationFunction_t(other.userValidationFunction_Boolean.at(i)));
}
}
bool hasBeenBuild;
ArgumentType argumentType;
std::string argumentName;
std::string argumentDescription;
/*
enum class ArgumentType {
Invalid, String, Integer, UnsignedInteger, Double, Boolean
};
*/
std::vector<storm::settings::Argument<std::string>::userValidationFunction_t> userValidationFunction_String;
std::vector<storm::settings::Argument<int_fast64_t>::userValidationFunction_t> userValidationFunction_Integer;
std::vector<storm::settings::Argument<uint_fast64_t>::userValidationFunction_t> userValidationFunction_UnsignedInteger;
std::vector<storm::settings::Argument<double>::userValidationFunction_t> userValidationFunction_Double;
std::vector<storm::settings::Argument<bool>::userValidationFunction_t> userValidationFunction_Boolean;
bool isOptional;
std::string defaultValue_String;
int_fast64_t defaultValue_Integer;
uint_fast64_t defaultValue_UnsignedInteger;
double defaultValue_Double;
bool defaultValue_Boolean;
bool hasDefaultValue;
bool validateDefaultForEach(std::string& errorMessageTarget) {
bool result = true;
switch (this->argumentType) {
case ArgumentType::String:
for (auto lambda: this->userValidationFunction_String) {
result = result && lambda(this->defaultValue_String, errorMessageTarget);
}
break;
case ArgumentType::Integer:
for (auto lambda: this->userValidationFunction_Integer) {
result = result && lambda(this->defaultValue_Integer, errorMessageTarget);
}
break;
case ArgumentType::UnsignedInteger:
for (auto lambda: this->userValidationFunction_UnsignedInteger) {
result = result && lambda(this->defaultValue_UnsignedInteger, errorMessageTarget);
}
break;
case ArgumentType::Double:
for (auto lambda: this->userValidationFunction_Double) {
result = result && lambda(this->defaultValue_Double, errorMessageTarget);
}
break;
case ArgumentType::Boolean:
for (auto lambda: this->userValidationFunction_Boolean) {
result = result && lambda(this->defaultValue_Boolean, errorMessageTarget);
}
break;
default: {
throw storm::exceptions::InternalTypeErrorException() << "Error: Missing Case in ArgumentBuilder's switch/case Code.";
}
}
return result;
}
};
}
}
#endif // STORM_SETTINGS_ARGUMENTBUILDER_H_