#ifndef STORM_SETTINGS_SETTINGSMANAGER_H_ #define STORM_SETTINGS_SETTINGSMANAGER_H_ #include <iostream> #include <utility> #include <functional> #include <unordered_map> #include <map> #include <vector> #include <memory> namespace storm { namespace settings { namespace modules { class CoreSettings; class IOSettings; class ModuleSettings; } class Option; /*! * Provides the central API for the registration of command line options and parsing the options from the * command line. Since this class is a singleton, the only instance is accessible via a call to the manager() * function. */ class SettingsManager { public: // Explicitely delete copy constructor SettingsManager(SettingsManager const&) = delete; void operator=(SettingsManager const&) = delete; /*! * This function parses the given command line arguments and sets all registered options accordingly. If the * command line cannot be matched using the known options, an exception is thrown. * * @param argc The number of command line arguments. * @param argv The command line arguments. */ void setFromCommandLine(int const argc, char const * const argv[]); /*! * This function parses the given command line arguments (represented by one big string) and sets all * registered options accordingly. If the command line cannot be matched using the known options, an * exception is thrown. * * @param commandLineString The command line arguments as one string. */ void setFromString(std::string const& commandLineString); /*! * This function parses the given command line arguments (represented by several strings) and sets all * registered options accordingly. If the command line cannot be matched using the known options, an * exception is thrown. * * @param commandLineArguments The command line arguments. */ void setFromExplodedString(std::vector<std::string> const& commandLineArguments); /*! * This function parses the given file and sets all registered options accordingly. If the settings cannot * be matched using the known options, an exception is thrown. */ void setFromConfigurationFile(std::string const& configFilename); /*! * This function prints a help message to the standard output. Optionally, a string can be given as a hint. * If it is 'all', the complete help is shown. Otherwise, the string is interpreted as a regular expression * and matched against the known modules and options to restrict the help output. * * @param hint A regular expression to restrict the help output or "all" for the full help text. */ void printHelp(std::string const& hint = "all") const; /*! * This function prints a help message for the specified module to the standard output. * * @param moduleName The name of the module for which to show the help. * @param maxLength The maximal length of an option name (necessary for proper alignment). */ void printHelpForModule(std::string const& moduleName, uint_fast64_t maxLength = 30) const; /*! * This function prints the version string to the command line. */ void printVersion() const; /*! * Retrieves the only existing instance of a settings manager. * * @return The only existing instance of a settings manager */ static SettingsManager& manager(); /*! * Sets the name of the tool. * @param name Name of the tool. * @param executableName Filename of the executable. */ void setName(std::string const& name, std::string const& executableName); /*! * Adds a new module with the given name. If the module could not be successfully added, an exception is * thrown. * * @param moduleSettings The settings of the module to add. */ void addModule(std::unique_ptr<modules::ModuleSettings>&& moduleSettings); /*! * Retrieves the settings of the module with the given name. * * @param moduleName The name of the module for which to retrieve the settings. * @return An object that provides access to the settings of the module. */ modules::ModuleSettings const& getModule(std::string const& moduleName) const; /*! * Retrieves the settings of the module with the given name. * * @param moduleName The name of the module for which to retrieve the settings. * @return An object that provides access to the settings of the module. */ modules::ModuleSettings& getModule(std::string const& moduleName); private: /*! * Constructs a new manager. This constructor is private to forbid instantiation of this class. The only * way to create a new instance is by calling the static manager() method. */ SettingsManager(); /*! * This destructor is private, since we need to forbid explicit destruction of the manager. */ virtual ~SettingsManager(); // The name of the tool std::string name; std::string executableName; // The registered modules. std::vector<std::string> moduleNames; std::unordered_map<std::string, std::unique_ptr<modules::ModuleSettings>> modules; // Mappings from all known option names to the options that match it. All options for one option name need // to be compatible in the sense that calling isCompatible(...) pairwise on all options must always return true. std::unordered_map<std::string, std::vector<std::shared_ptr<Option>>> longNameToOptions; std::unordered_map<std::string, std::vector<std::shared_ptr<Option>>> shortNameToOptions; // A mapping of module names to the corresponding options. std::unordered_map<std::string, std::vector<std::shared_ptr<Option>>> moduleOptions; // A list of long option names to keep the order in which they were registered. This is, for example, used // to match the regular expression given to the help option against the option names. std::vector<std::string> longOptionNames; /*! * Adds the given option to the known options. * * @param option The option to add. */ void addOption(std::shared_ptr<Option> const& option); /*! * Sets the arguments of the given option from the provided strings. * * @param optionName The name of the option. This is only used for error output. * @param option The option for which to set the arguments. * @param argumentCache The arguments of the option as string values. */ static void setOptionArguments(std::string const& optionName, std::shared_ptr<Option> option, std::vector<std::string> const& argumentCache); /*! * Sets the arguments of the options matching the given name from the provided strings. * * @param optionName The name of the options for which to set the arguments. * @param optionMap The mapping from option names to options. * @param argumentCache The arguments of the option as string values. */ static void setOptionsArguments(std::string const& optionName, std::unordered_map<std::string, std::vector<std::shared_ptr<Option>>> const& optionMap, std::vector<std::string> const& argumentCache); /*! * Checks whether the given option is compatible with all options with the given name in the given mapping. */ static bool isCompatible(std::shared_ptr<Option> const& option, std::string const& optionName, std::unordered_map<std::string, std::vector<std::shared_ptr<Option>>> const& optionMap); /*! * Inserts the given option to the options with the given name in the given map. * * @param name The name of the option. * @param option The option to add. * @param optionMap The map into which the option is to be inserted. */ static void addOptionToMap(std::string const& name, std::shared_ptr<Option> const& option, std::unordered_map<std::string, std::vector<std::shared_ptr<Option>>>& optionMap); /*! * Prepares some modules for further changes. * Checks all modules for consistency by calling their respective check method. */ void finalizeAllModules(); /*! * Retrieves the (print) length of the longest option of all modules. * * @return The length of the longest option. */ uint_fast64_t getPrintLengthOfLongestOption() const; /*! * Retrieves the (print) length of the longest option in the given module, so we can align the options. * * @param moduleName The module name for which to retrieve the length of the longest option. * @return The length of the longest option name. */ uint_fast64_t getPrintLengthOfLongestOption(std::string const& moduleName) const; /*! * Parses the given file and stores the settings in the returned map. * * @param filename The name of the file that is to be scanned for settings. * @return A mapping of option names to the argument values (represented as strings). */ std::map<std::string, std::vector<std::string>> parseConfigFile(std::string const& filename) const; }; /*! * Retrieves the settings manager. * * @return The only settings manager. */ SettingsManager const& manager(); /*! * Retrieves the settings manager. * * @return The only settings manager. */ SettingsManager& mutableManager(); /*! * Add new module to use for the settings. The new module is given as a template argument. */ template<typename SettingsType> void addModule() { static_assert(std::is_base_of<storm::settings::modules::ModuleSettings, SettingsType>::value, "Template argument must be derived from ModuleSettings"); mutableManager().addModule(std::unique_ptr<modules::ModuleSettings>(new SettingsType())); } /*! * Initialize the settings manager with all available modules. * @param name Name of the tool. * @param executableName Filename of the executable. */ void initializeAll(std::string const& name, std::string const& executableName); /*! * Get module. The type of the module is given as a template argument. * * @return The module. */ template<typename SettingsType> SettingsType const& getModule() { static_assert(std::is_base_of<storm::settings::modules::ModuleSettings, SettingsType>::value, "Template argument must be derived from ModuleSettings"); return dynamic_cast<SettingsType const&>(manager().getModule(SettingsType::moduleName)); } /*! * Retrieves the markov chain settings in a mutable form. This is only meant to be used for debug purposes or very * rare cases where it is necessary. * * @return An object that allows accessing and modifying the markov chain settings. */ storm::settings::modules::CoreSettings& mutableCoreSettings(); /*! * Retrieves the IO settings in a mutable form. This is only meant to be used for debug purposes or very * rare cases where it is necessary. * * @return An object that allows accessing and modifying the IO settings. */ storm::settings::modules::IOSettings& mutableIOSettings(); } // namespace settings } // namespace storm #endif /* STORM_SETTINGS_SETTINGSMANAGER_H_ */