Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Actions/MapOfActions.hpp

    r7e6b00 r0bb05a  
    99#define MAPOFACTIONS_HPP_
    1010
    11 #include "Helpers/Assert.hpp"
    1211#include <boost/program_options.hpp>
     12#include <boost/lexical_cast.hpp>
     13
    1314#include <map>
    1415#include <set>
     16#include <vector>
     17#include <typeinfo>
     18
     19#include "Exceptions/IllegalTypeException.hpp"
     20#include "Exceptions/MissingValueException.hpp"
     21#include "Helpers/Assert.hpp"
     22#include "Patterns/Singleton.hpp"
    1523
    1624class MapOfActionsTest;
    1725
    18 #include "Patterns/Singleton.hpp"
     26class Box;
     27class atom;
     28class element;
     29class molecule;
     30class Vector;
    1931
    2032namespace po = boost::program_options;
    2133
     34using boost::lexical_cast;
     35
     36/** Central class for adding functionality to the code.
     37 *
     38 * In Molecuilder everything that can be done - such as adding atoms,
     39 * translating molecules, saving bind information - is an Action.
     40 *
     41 * In order to reference Action's with what the user sees, this class is the
     42 * mediator.
     43 *
     44 * An Action is described to the user by:
     45 * -# a name (this is the most important information)
     46 * -# a description
     47 * -# a shortform (single letter for use on the command line)
     48 * -# a text menu it resides in
     49 * -# the type of its argument
     50 * -# the command line category
     51 *
     52 * The Action::NAME is the most important information because every Action
     53 * registers itself automatically with the ActionRegistry and can be retrieved
     54 * therefrom and from this MapOfActions simply by knowing its name alone.
     55 *
     56 * In the constructor of MapOfActions all this is set.
     57 *
     58 * Note that Action will require input from the user. This is done via class
     59 * Query.
     60 *
     61 * And note also that MapOfActions actually contains more than just all
     62 * Actions: There are a number of names that actually are just arguments to
     63 * actions (e.g. "output-file").
     64 *
     65 * <h1> Howto add an Action</h1>
     66 *
     67 * Let us assume your new action (class) is called SuperDuperAction, consisting
     68 * of two files SuperDuperAction.cpp and SuperDuperAction.hpp.
     69 *
     70 * Furthermore, let's say you Action needs two values: a double value as a
     71 * upper threshold and a string which is the name of the output file.
     72 *
     73 * <h2> Command Line preliminaries </h2>
     74 *
     75 * You have to decide whether (for the command line) it makes sense to have an
     76 * extra argument requesting the arguments, or one should be the argument of
     77 * your action. I.e. your action name is "super-duper", then the use may
     78 * call your action like this:
     79 *
     80 * ./molecuilder --super-duper 4 --output-file test.dat
     81 *
     82 * Here, we have picked the threshold as the value for your action and the
     83 * name of the output file is given by an additional argument. Of course,
     84 * it can be the other way round or by two arguments such as here:
     85 *
     86 * ./molecuilder --super-duper --threshold 4 --output-file test.dat
     87 *
     88 * It depends on what possible arguments are already there (don't make up
     89 * new ones if present ones actually make sense for your action) and which
     90 * argument is more natural or closer to what your action does.
     91 *
     92 * <h2> Menu preliminaries </h2>
     93 *
     94 * Whatever you decide, your action will need some Query dialogs to request
     95 * the necessary information from the user, either via a command line
     96 * argument (--output-file) via a text dialog (referenced by "output-file")
     97 * or via a graphical dialog (same reference). And therein, the names
     98 * of the arguments have to re-appear.
     99 *
     100 * Then, the following steps have to be done to incorporate your Action:
     101 * -# create a unique name for your action (no capital letters) to reference
     102 *    it, this name has to appear in the file SuperDuperAction.cpp, e.g.
     103 *    "super-duper"
     104 * -# pick names the other required arguments, best if they are already
     105 *    present in the MapOfActions. They have to appear in Query's in the
     106 *    code of your Action.
     107 * -# With this name create entries in the following maps for the action
     108 *    name and for each names of a desired addtional argument if not present:
     109 *   -# DescriptionMap, a catchy description of what your action does
     110 *   -# TypeMap, see MapOfActions::OptionTypes for possible types of the single
     111 *      argument it takes.
     112 *   -# MenuContainsActionMap, in which menu should your action appear
     113 *   -# ShortFormMap (optional), single letter for command line call
     114 *   -# DefaultValueMap (optional), the default value (always a string)
     115 * -# add to one of the command line sets by the following categories
     116 *   -# generic - generic options (i.e. not one of the others)
     117 *   -# config - action/argument only considers internal bevahior, user
     118 *      does not have to see it while still having full functionality
     119 *   -# hidden - this should be hidden from the user
     120 *   -# visible - this should be visible to the user
     121 *   -# inputfile - this should only be parsed from an input file, not
     122 *      from command line
     123 * -# add to a menu, i.e. make an entry in MenuContainsActionMap.
     124 * -# add header file SuperDuperAction.hpp to MapOfActions.cpp and instantiate
     125 *    your action in populateMenu() (mind the sorting: 1. menu,
     126 *    2. alphabetical)
     127 *
     128 *  And that's.
     129 *
     130 *  Now, your action can be called from the command line, within the text
     131 *  menu and the graphical user interface.
     132 *
     133 */
    22134class MapOfActions : public Singleton<MapOfActions> {
    23135  friend class Singleton<MapOfActions>;
    24136  friend class MapOfActionsTest;
    25137public:
    26   enum OptionTypes { None, Boolean, Integer, ListOfInts, Double, ListOfDoubles, String, Axis, Vector, Box, Molecule, ListOfMolecules, Atom, ListOfAtoms, Element, ListOfElements };
     138  enum OptionTypes { None, Boolean, Integer, ListOfIntegers, Double, ListOfDoubles, String, ListOfStrings, Vector, ListOfVectors, Box, Molecule, ListOfMolecules, Atom, ListOfAtoms, Element, ListOfElements };
    27139
    28140  // getter for the action descriptions and short forms
    29   std::string getDescription(string actionname);
    30   std::string getKeyAndShortForm(string actionname);
    31   std::string getShortForm(string actionname);
    32   map <std::string, std::string> getShortFormToActionMap();
     141  std::string getDescription(std::string actionname);
     142  std::string getKeyAndShortForm(std::string actionname);
     143  std::string getShortForm(std::string actionname);
     144  std::map <std::string, std::string> getShortFormToActionMap();
    33145
    34146  void AddOptionsToParser();
    35147
    36148  // check presence and getter for action type
    37   bool hasValue(string actionname);
    38   bool isShortFormPresent(string shortform);
    39   enum OptionTypes getValueType(string actionname);
    40 
    41   set<string> generic;
    42   set<string> config;
    43   set<string> hidden;
    44   set<string> visible;
    45   set<string> inputfile;
     149  bool hasValue(std::string actionname);
     150  bool isShortFormPresent(std::string shortform);
     151  std::string  getValueType(std::string actionname);
     152
     153  std::set<std::string> generic;
     154  std::set<std::string> config;
     155  std::set<std::string> hidden;
     156  std::set<std::string> visible;
     157  std::set<std::string> inputfile;
     158
     159  std::multimap <std::string, std::string> MenuContainsActionMap;
     160  std::map <std::string, std::pair<std::string,std::string> > MenuDescription;
     161
     162  // instantiates and puts all known actions into the ActionRegistry
     163  void populateActions();
     164
     165  void queryCurrentValue(const char * name, class atom * &_T);
     166  void queryCurrentValue(const char * name, class element * &_T);
     167  void queryCurrentValue(const char * name, class molecule * &_T);
     168  void queryCurrentValue(const char * name, class Box &_T);
     169  void queryCurrentValue(const char * name, class Vector &_T);
     170  void queryCurrentValue(const char * name, std::vector<atom *>&_T);
     171  void queryCurrentValue(const char * name, std::vector<element *>&_T);
     172  void queryCurrentValue(const char * name, std::vector<molecule *>&_T);
     173  template<typename T> void queryCurrentValue(const char * name, T &_T)
     174  {
     175    if (typeid( T ) == *TypeMap[name]) { // constructor of type_info is private, hence can only store by ref or ptr
     176      if (CurrentValue.find(name) == CurrentValue.end())
     177        throw MissingValueException(__FILE__, __LINE__);
     178      _T = lexical_cast<T>(CurrentValue[name].c_str());
     179      CurrentValue.erase(name);
     180    } else
     181      throw IllegalTypeException(__FILE__,__LINE__);
     182  }
     183  template<typename T> void queryCurrentValue(const char * name, std::vector<T> &_T)
     184  {
     185    T temp;
     186    if (typeid( std::vector<T> ) == *TypeMap[name]) { // constructor of type_info is private, hence can only store by ref or ptr
     187      if (CurrentValue.find(name) == CurrentValue.end())
     188        throw MissingValueException(__FILE__, __LINE__);
     189      std::istringstream stream(CurrentValue[name]);
     190      CurrentValue.erase(name);
     191      while (!stream.fail()) {
     192        stream >> temp >> std::ws;
     193        _T.push_back(temp);
     194      }
     195    } else
     196      throw IllegalTypeException(__FILE__,__LINE__);
     197  }
     198
     199  void setCurrentValue(const char * name, class atom * &_T);
     200  void setCurrentValue(const char * name, class element * &_T);
     201  void setCurrentValue(const char * name, class molecule * &_T);
     202  void setCurrentValue(const char * name, class Box &_T);
     203  void setCurrentValue(const char * name, class Vector &_T);
     204  void setCurrentValue(const char * name, std::vector<atom *>&_T);
     205  void setCurrentValue(const char * name, std::vector<element *>&_T);
     206  void setCurrentValue(const char * name, std::vector<molecule *>&_T);
     207  template<class T> void setCurrentValue(const char * name, T &_T)
     208  {
     209    std::ostringstream stream;
     210    if (typeid( T ) == *TypeMap[name]) {  // constructor of type_info is private, hence can only store by ref or ptr
     211      stream << _T;
     212      CurrentValue[name] = stream.str();
     213    } else
     214      throw IllegalTypeException(__FILE__,__LINE__);
     215  }
     216  template<class T> void setCurrentValue(const char * name, std::vector<T> &_T)
     217  {
     218    std::ostringstream stream;
     219    if (typeid( std::vector<T> ) == *TypeMap[name]) {  // constructor of type_info is private, hence can only store by ref or ptr
     220      std::ostringstream stream;
     221      for (typename std::vector<T>::iterator iter = _T.begin(); iter != _T.end(); ++iter) {
     222        stream << (*iter) << " ";
     223      }
     224      CurrentValue[name] = stream.str();
     225    } else
     226      throw IllegalTypeException(__FILE__,__LINE__);
     227  }
     228
    46229
    47230private:
     
    51234
    52235  // lookup list from our configs to the ones of CommandLineParser
    53   map< set<std::string> *, po::options_description *> CmdParserLookup;
     236  std::map< std::set<std::string> *, po::options_description *> CmdParserLookup;
    54237
    55238  // map of the action names and their description
    56   map<std::string, std::string> DefaultValue;
    57   map<std::string, std::string> DescriptionMap;
    58   map<std::string, std::string> ShortFormMap;
    59   map<std::string, enum OptionTypes > TypeMap;
     239  std::map<std::string, std::string> CurrentValue;
     240  std::map<std::string, std::string> DescriptionMap;
     241  std::map<std::string, std::string> ShortFormMap;
     242  std::map<std::string, const std::type_info * > TypeMap;
     243  std::map<const std::type_info *, enum OptionTypes > TypeEnumMap;
    60244};
    61245
Note: See TracChangeset for help on using the changeset viewer.