/* * ValueStorage.hpp * * Created on: Jul 22, 2010 * Author: heber */ #ifndef VALUESTORAGE_HPP_ #define VALUESTORAGE_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include "Actions/OptionTrait.hpp" #include "Actions/OptionRegistry.hpp" #include "CodePatterns/Assert.hpp" #include "CodePatterns/Singleton.hpp" #include #include class MatrixContent; class Vector; /** Base type for all exceptions regarding ValueStorage class. * */ struct ValueStorageException : virtual std::exception, virtual boost::exception { }; /** ========================== General error information ================== */ /** Exception information for ValueStorageException: name of option. */ typedef boost::error_info ValueStorageOptionName; /** Exception information for ValueStorageException: name of type. */ typedef boost::error_info ValueStorageTypeName; /** Exception information for ValueStorageException: pair of names of two types. */ typedef boost::error_info< struct tag_ValueStorageTypeName, std::pair > ValueStoragePairTypeName; /** ============================ Specific exceptions ====================== */ /** Exception thrown when ValueStorage is given an illegal type for a specific option. */ struct IllegalTypeException : virtual ValueStorageException { }; /** Exception thrown when ValueStorage is missing a requested value. */ struct MissingValueException : virtual ValueStorageException { }; class MapOfActionsTest; class Box; class atom; class element; class molecule; class Vector; class RandomNumberDistribution_Parameters; namespace po = boost::program_options; using boost::lexical_cast; #include "CodePatterns/Singleton.hpp" /** ValueStorage serves as a mediator to MapOfActions. * This is needed to relax inter-dependencies between the Queries and the Actions. * I.e. this is the interface implemented in MapOfActions which both can safely rely on * to store&retrieve/exchange values. * * \section (ValueStorage howto) * * If you ever need to add a particular class to the ValueStorage, do as follows: * -# add a specialized queryCurrentValue and setCurrentValue to the definition * of ValueStorage. * -# implement both in the declaration of ValueStorage. * -# in the implementation either directly implement the serializing of the * class' members to a stringstream or use an already implemented operator<< * or operator<<, respectively. * */ class ValueStorage : public Singleton { friend class Singleton; public: bool isCurrentValuePresent(const char *name) const; void queryCurrentValue(const char * name, const atom * &_T); void queryCurrentValue(const char * name, const element * &_T); void queryCurrentValue(const char * name, const molecule * &_T); void queryCurrentValue(const char * name, class Box &_T); void queryCurrentValue(const char * name, class Vector &_T); void queryCurrentValue(const char * name, class BoxVector &_T); void queryCurrentValue(const char * name, class RandomNumberDistribution_Parameters &_T); void queryCurrentValue(const char * name, std::vector&_T); void queryCurrentValue(const char * name, std::vector&_T); void queryCurrentValue(const char * name, std::vector&_T); void queryCurrentValue(const char * name, boost::filesystem::path&_T); /** Gets a value from the storage * If the value is not present, an ASSERT is thrown unless optional is set to true. * \param _T key of value * \param optional whether this value is optional, i.e. may actually not be in the storage (i.e. may return false in this case). * \return true - value present, false - value not present (only given when optional set to true) */ template void queryCurrentValue(const char * name, T &_T) { if (typeid( T ) == *(OptionRegistry_instance.getOptionByName(name)->getType())) { // constructor of type_info is private, hence can only store by ref or ptr if (CurrentValueMap.find(name) == CurrentValueMap.end()) throw MissingValueException() << ValueStorageOptionName(name); _T = lexical_cast(CurrentValueMap[name].c_str()); CurrentValueMap.erase(name); } else throw IllegalTypeException() << ValueStorageOptionName(name) << ValueStoragePairTypeName(std::make_pair( typeid(_T).name(), OptionRegistry_instance.getOptionByName(name)->getTypeName().c_str()) ); } template void queryCurrentValue(const char * name, std::vector &_T) { T temp; if (typeid( std::vector ) == *(OptionRegistry_instance.getOptionByName(name)->getType())) { // constructor of type_info is private, hence can only store by ref or ptr if (CurrentValueMap.find(name) == CurrentValueMap.end()) throw MissingValueException() << ValueStorageOptionName(name); std::istringstream stream(CurrentValueMap[name]); CurrentValueMap.erase(name); while (!stream.fail()) { stream >> temp >> std::ws; if (!stream.fail()) { _T.push_back(temp); } } } else throw IllegalTypeException() << ValueStorageOptionName(name) << ValueStoragePairTypeName(std::make_pair( typeid(_T).name(), OptionRegistry_instance.getOptionByName(name)->getTypeName().c_str()) ); } void setCurrentValue(const char * name, const atom * &_T); void setCurrentValue(const char * name, const element * &_T); void setCurrentValue(const char * name, const molecule * &_T); void setCurrentValue(const char * name, class Box &_T); void setCurrentValue(const char * name, class Vector &_T); void setCurrentValue(const char * name, class RandomNumberDistribution_Parameters &_T); void setCurrentValue(const char * name, std::vector&_T); void setCurrentValue(const char * name, std::vector&_T); void setCurrentValue(const char * name, std::vector&_T); void setCurrentValue(const char * name, boost::filesystem::path&_T); /** Sets a value in the storage. * \param name key of value * \param _T value */ template void setCurrentValue(const char * name, T &_T) { std::ostringstream stream; if (typeid( T ) == *(OptionRegistry_instance.getOptionByName(name)->getType())) { // constructor of type_info is private, hence can only store by ref or ptr stream << _T; CurrentValueMap[name] = stream.str(); } else throw IllegalTypeException() << ValueStorageOptionName(name) << ValueStoragePairTypeName(std::make_pair( typeid(_T).name(), OptionRegistry_instance.getOptionByName(name)->getTypeName().c_str()) ); } /** Sets a value in the storage. * \param name key of value * \param _T value */ template void setCurrentValue(const char * name, std::vector &_T) { std::ostringstream stream; if (typeid( std::vector ) == *(OptionRegistry_instance.getOptionByName(name)->getType())) { // constructor of type_info is private, hence can only store by ref or ptr std::ostringstream stream; for (typename std::vector::const_iterator iter = _T.begin(); iter != _T.end(); ++iter) { stream << (*iter) << " "; } CurrentValueMap[name] = stream.str(); } else throw IllegalTypeException() << ValueStorageOptionName(name) << ValueStoragePairTypeName(std::make_pair( typeid(_T).name(), OptionRegistry_instance.getOptionByName(name)->getTypeName().c_str()) ); } const std::string getCurrentValue(std::string actionname); protected: ValueStorage(); ~ValueStorage(); std::map CurrentValueMap; OptionRegistry &OptionRegistry_instance; }; #endif /* VALUESTORAGE_HPP_ */