/* * Reaction_impl.hpp * * Created on: Oct 13, 2011 * Author: heber */ /** These macros define the following functions, necessary but repetitive for * every Action: * -# Dialog* fillDialog() * -# action command (e.g. AnalysisMolecularVolume() ) * -# void getParametersfromValuStorage() * -# struct Action...Parameters * * For this, the user has the define the following values, each with * parenthesis, for the values/parameters the action needs * -# paramtypes, e.g. (int)(double) * -# paramtokens, e.g. ("Z")("length") * -# paramreferences, e.g. (Z)(length) * and for additional values/parameters to save in the state * -# statetypes, e.g. (int)(double) * -# statereferences, e.g. (Z)(length) * and the name and category of the action * -# CATEGORY, e.g. Analysis * -# ACTIONNAME, e.g. MolecularVolume */ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include "Actions/ActionQueue.hpp" #include "Actions/toCLIString.hpp" #include "Actions/toPythonString.hpp" // some derived names: if CATEGORY is not given, we don't prefix with it #ifdef CATEGORY #define REACTION BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, Action)) #define COMMAND BOOST_PP_CAT(CATEGORY, ACTIONNAME) #define STATE BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, State)) #define PARAMS BOOST_PP_CAT(CATEGORY, BOOST_PP_CAT(ACTIONNAME, Parameters)) #else #define REACTION BOOST_PP_CAT(ACTIONNAME, Action) #define COMMAND ACTIONNAME #define STATE BOOST_PP_CAT(ACTIONNAME, State) #define PARAMS BOOST_PP_CAT(ACTIONNAME, Parameters) #endif // check if no lists given #ifndef paramtypes #define MAXPARAMTYPES 0 #else #define MAXPARAMTYPES BOOST_PP_SEQ_SIZE(paramtypes) #endif #ifndef statetypes #define MAXSTATETYPES 0 #else #define MAXSTATETYPES BOOST_PP_SEQ_SIZE(statetypes) #endif // check user has given name and category #ifndef ACTIONNAME ERROR: No "ACTIONNAME" defined in: __FILE__ #endif // calculate numbers and check whether all have same size #ifdef paramtokens BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXPARAMTYPES, BOOST_PP_SEQ_SIZE(paramtokens)),\ ERROR: There are not the same number of "paramtokens" and "paramtypes" in: __FILE__ \ ) #endif #ifdef paramreferences BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXPARAMTYPES, BOOST_PP_SEQ_SIZE(paramreferences)),\ ERROR: There are not the same number of "paramtokens" and "paramreferences" in: __FILE__ \ ) #endif #ifdef statetypes BOOST_PP_ASSERT_MSG(BOOST_PP_EQUAL(MAXSTATETYPES, BOOST_PP_SEQ_SIZE(statereferences)),\ ERROR: There are not the same number of "statetypes" and "statereferences" in: __FILE__ \ ) #endif // set the return type #ifndef returntype BOOST_PP_ASSERT_MSG(0,\ ERROR: No returntype is defined in __FILE__ \ ) #endif #define RETURNTYPE returntype // print a list of type ref followed by a separator, i.e. "int i;" #define initialiser_print(z,n,initialiserlist) \ BOOST_PP_SEQ_ELEM(n, initialiserlist) \ (BOOST_PP_CAT(_, BOOST_PP_SEQ_ELEM(n, initialiserlist))), // print a list of ref(_ref) followed by a separator, i.e. "id(_id)," #define type_print(z,n,TYPELIST, VARLIST, separator) \ BOOST_PP_SEQ_ELEM(n, TYPELIST) \ BOOST_PP_SEQ_ELEM(n, VARLIST)\ separator // print a list of type ref followed, i.e. "int i, double position" #define type_list(z,n,TYPELIST,VARLIST) \ BOOST_PP_COMMA_IF(n)\ BOOST_PP_SEQ_ELEM(n, TYPELIST) \ BOOST_PP_SEQ_ELEM(n, VARLIST) // prints dialog->query calls for paramtypes with tokens #define dialog_print(z,n,unused) \ dialog->query<\ BOOST_PP_SEQ_ELEM(n, paramtypes)\ >(\ BOOST_PP_SEQ_ELEM(n, paramtokens)\ , Traits.getDescription()\ ); // prints command line call for this Action for paramtypes with tokens #define outputAsCLI_print(z,n,output) \ output << \ BOOST_PP_IF(n, " --", "--") \ << \ BOOST_PP_SEQ_ELEM(n, paramtokens) \ << " " << toCLIString(params. \ BOOST_PP_SEQ_ELEM(n, paramreferences) \ .get()); // prints if statement to check two strings (paramtokens[n] vs. TOKEN) #define checkpresenttoken_print(z, n, TOKEN, booltoken) \ if ( std::string(\ BOOST_PP_SEQ_ELEM(n, paramtokens) )\ == getName()) \ booltoken = false; // prints command line call for this Action for paramtypes with tokens #define outputAsPython_print(z,n,output) \ output << \ BOOST_PP_IF(n, ", ", "") \ << "\"" << toPythonString(params. \ BOOST_PP_SEQ_ELEM(n, paramreferences) \ .get()) \ << "\""; // prints set/queryCurrentValue (command) for paramreferences and paramtokens #define value_print(z, n, container, prefix) \ prefix \ BOOST_PP_SEQ_ELEM(n, container)\ .set(\ BOOST_PP_SEQ_ELEM(n, container)\ ); // prints set/queryCurrentValue (command) for paramreferences and paramtokens #define valuetype_print(z,n,container, types, prefix) \ prefix \ BOOST_PP_SEQ_ELEM(n, container) \ .setAsString( \ BOOST_PP_SEQ_ELEM(n, container) \ ); #define stringtype std::string #define type2string(s, data, elem) \ stringtype #include "Actions/ActionRegistry.hpp" //#include "Actions/ActionTraits.hpp" #include "UIElements/Dialog.hpp" #ifdef paramtokens #define statenecessary 1 #endif #ifndef statetokens #define statenecessary 1 #endif namespace MoleCuilder { // =========== constructor =========== REACTION::REACTION () : Reaction< RETURNTYPE >(ActionTraits< REACTION >()) {} // =========== destructor =========== REACTION::~REACTION () { //std::cout << "Action REACTION is being destroyed." << std::endl; } // =========== fill a dialog =========== Dialog* REACTION::fillDialog(Dialog *dialog) { ASSERT(dialog,"No Dialog given when filling actionname's dialog"); #if BOOST_PP_EQUAL(MAXPARAMTYPES,0) dialog->queryEmpty(TOKEN, Traits.getDescription()); #else #define BOOST_PP_LOCAL_MACRO(n) dialog_print(~, n, ~) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif return dialog; }; // =========== output as CLI =========== void REACTION::outputAsCLI(std::ostream &ost) const { // check whether TOKEN is also an option // is a bit ugly as preprocessor cannot compare strings bool status = true; #if defined paramtokens && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) #define BOOST_PP_LOCAL_MACRO(n) checkpresenttoken_print(~, n, TOKEN, status) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif if (status) { ost << "--" << TOKEN; #if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) ost << " "; #endif } // then print option along with each argument if set #if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) #define BOOST_PP_LOCAL_MACRO(n) outputAsCLI_print(~, n, ost) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif } // =========== output as PYTHTON =========== void REACTION::outputAsPython(std::ostream &ost, const std::string &prefix) const { // print prefix and action command ost << prefix << "." << BOOST_PP_STRINGIZE( COMMAND ) << "("; // then print option along with each argument if set #if defined paramtypes && defined paramreferences && BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) #define BOOST_PP_LOCAL_MACRO(n) outputAsCLI_print(~, n, ost) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ost << ")" << std::endl; } // =========== command for calling action directly =========== RETURNTYPE COMMAND( #if defined paramtypes && defined paramreferences #define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, paramtypes, paramreferences) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ) { Action *ToCall = ActionQueue::getInstance().getActionByName( TOKEN ); //->clone(params); //REACTION::PARAMS params; #if BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) #define BOOST_PP_LOCAL_MACRO(n) value_print(~, n, setCurrentValue, ) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ActionQueue::getInstance().queueAction( ToCall, Action::NonInteractive); Reaction< RETURNTYPE > * resultaction = static_cast *>(ToCall); ASSERT( resultaction != NULL, " COMMAND - static cast to Reaction type failed."); ASSERT( resultaction->hasResult (), " _COMMAND - result is not done yet?"); return resultaction->getResult(); }; RETURNTYPE BOOST_PP_CAT( COMMAND, _stringargs)( #if defined paramtypes && defined paramreferences #define BOOST_PP_LOCAL_MACRO(n) type_list(~, n, BOOST_PP_SEQ_TRANSFORM( type2string, , paramtypes), paramreferences) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ) { Action *ToCall = ActionQueue::getInstance().getActionByName( TOKEN ); //->clone(params); //REACTION::PARAMS params; #if BOOST_PP_NOT_EQUAL(MAXPARAMTYPES,0) #define BOOST_PP_LOCAL_MACRO(n) valuetype_print(~, n, setCurrentValueByString, ) #define BOOST_PP_LOCAL_LIMITS (0, MAXPARAMTYPES-1) #include BOOST_PP_LOCAL_ITERATE() #endif ActionQueue::getInstance().queueAction( ToCall, Action::NonInteractive); Reaction< RETURNTYPE > * resultaction = static_cast *>(ToCall); ASSERT( resultaction != NULL, " COMMAND - static cast to Reaction type failed."); ASSERT( resultaction->hasResult (), " _COMMAND - result is not done yet?"); return resultaction->getResult(); }; } // free up defines #undef paramtypes #undef paramtokens #undef paramreferences #undef MAXPARAMTYPES #undef returntype #undef RETURNTYPE #undef type2string #undef stringtype #undef initialiser_print #undef type_print #undef type_list #undef dialog_print #undef value_print #undef valuetype_print #undef REACTION #undef COMMAND #undef PARAMS #undef STATE #undef ACTIONNAME #undef CATEGORY #undef TOKEN