7 #ifndef DATATOOLS_UI_REFLECTIVE_COMMAND_INL_H 8 #define DATATOOLS_UI_REFLECTIVE_COMMAND_INL_H 15 #include <boost/lexical_cast.hpp> 16 #include <boost/program_options/options_description.hpp> 18 #include <camp/classget.hpp> 19 #include <camp/userobject.hpp> 20 #include <camp/value.hpp> 21 #include <camp/args.hpp> 22 #include <camp/class.hpp> 23 #include <camp/errors.hpp> 24 #include <camp/enum.hpp> 25 #include <camp/type.hpp> 47 const std::string & func_name_,
48 const std::string & name_,
49 const std::string & description_,
52 (name_.empty() ? func_name_ : name_),
71 _func_name_ = func_name_;
80 bool forbid_short_ui_options =
false;
81 std::string classname(datatools::detail::reflection::guid<Type>());
83 DT_LOG_DEBUG(logging,
"classname = '" << classname <<
"'");
84 DT_LOG_DEBUG(logging,
"List of registered metaclasses:");
85 for (std::size_t i = 0; i < camp::classCount(); i++) {
86 const camp::Class & metaclass = camp::classByIndex(i);
87 DT_LOG_DEBUG(logging,
"Class: '" << metaclass.name() <<
"'");
92 camp::classByName(classname);
93 }
catch (std::exception & error) {
95 "No class '" << classname <<
"' with reflection support: " << error.what());
97 const camp::Class & target_class = camp::classByName(classname);
99 std::string funcname = _func_name_;
100 if (funcname.empty()) {
106 "Class '" << classname <<
"' has no function '" << funcname <<
"'!");
107 _func_ = &target_class.function(funcname);
116 builder.
build(_method_);
119 _method_.tree_dump(std::clog,
"Reflective command description : ",
"[trace]: ");
123 if (_method_.has_display_name()) {
128 if (_method_.has_terse_description()) {
140 namespace po = boost::program_options;
141 po::options_description_easy_init easy_init
142 = opts.add_options();
145 std::vector<std::string> input_arg_names;
146 _method_.build_list_of_input_argument_names(input_arg_names);
149 std::vector<std::string> output_arg_names;
150 _method_.build_list_of_output_argument_names(output_arg_names);
153 "Class '" << classname <<
"' function '" << funcname <<
"' has too many output parameters!");
155 for (std::size_t iarg = 0; iarg < input_arg_names.size(); iarg++) {
157 std::string arg_name = arg.
get_name();
158 std::string arg_value_name =
"value";
159 std::string arg_help =
"";
163 if (arg_help.back() !=
'\n') arg_help +=
'\n';
166 std::string dd_type_id;
171 std::string type_label;
172 std::string type_details;
174 type_label =
"boolean";
176 type_label =
"integer";
178 type_label =
"string";
182 type_details =
"dimensionless";
184 std::ostringstream type_details_oss;
189 type_details = type_details_oss.str();
192 type_label =
"enumeration";
193 if (!dd_type_id.empty()) {
194 type_details = dd_type_id;
199 std::ostringstream rang_desc;
200 rang_desc <<
"Rank: " << iarg <<
"\n";
201 arg_help += rang_desc.str();
203 std::ostringstream type_desc;
204 type_desc <<
"Type: '" << type_label <<
"'";
205 if (!type_details.empty()) {
206 type_desc <<
" (" << type_details <<
")";
209 if (type_desc.str().length()) {
210 arg_help += type_desc.str();
213 easy_init(arg_name.c_str(),
214 po::value<datatools::ui::wrapped_boolean>()
215 ->value_name(arg_value_name),
219 easy_init(arg_name.c_str(),
220 po::value<datatools::ui::wrapped_integer>()
221 ->value_name(arg_value_name),
224 forbid_short_ui_options =
true;
226 easy_init(arg_name.c_str(),
227 po::value<std::string>()
228 ->value_name(arg_value_name),
233 easy_init(arg_name.c_str(),
234 po::value<datatools::ui::wrapped_real_without_unit>()
235 ->value_name(arg_value_name),
239 easy_init(arg_name.c_str(),
240 po::value<datatools::ui::wrapped_real_with_unit>()
241 ->value_name(arg_value_name),
245 forbid_short_ui_options =
true;
247 if (!dd_type_id.empty()) {
248 std::ostringstream supported_value_desc;
249 supported_value_desc <<
"Allowed values are:\n";
250 const camp::Enum & metaenum = camp::enumByName(dd_type_id);
251 DT_LOG_TRACE(logging,
"Enum name = '" << metaenum.name());
252 for (std::size_t ivalue = 0; ivalue < metaenum.size(); ivalue++) {
253 const camp::Enum::Pair & value_pair = metaenum.pair(ivalue);
254 supported_value_desc <<
" - \"" << value_pair.name <<
"\"\n";
256 if (supported_value_desc.str().length()) {
257 arg_help += supported_value_desc.str();
260 easy_init(arg_name.c_str(),
261 po::value<std::string>()
262 ->value_name(arg_value_name),
265 DT_THROW(std::logic_error,
"Class '" << classname <<
"' function '" << funcname <<
"': " 266 <<
"unsupported data type for input argument #" << iarg <<
"!");
270 args.add(arg_name.c_str(), 1);
273 if (forbid_short_ui_options) {
280 template <
class Type>
291 template <
class Type>
302 if (!_func_->callable(targetObj)) {
306 "Building args from the vmap...");
311 arg_builder.
build(args);
313 "Calling function '" << _func_->name() <<
"'...");
314 camp::Value returned_value = _func_->call(targetObj, args);
315 if (returned_value.type() != camp::noType) {
317 "Returned value = '" << returned_value <<
"'...");
318 repr(std::clog, returned_value, _method_.get_unique_returned());
319 std::clog << std::endl;
321 }
catch (std::exception & error) {
332 template <
class Type>
334 const camp::Value & value_,
338 if (value_.type() == camp::boolType) {
341 }
else if (value_.type() == camp::intType) {
344 }
else if (value_.type() == camp::realType) {
345 double value = value_;
351 std::string display_unit;
372 }
else if (value_.type() == camp::stringType) {
373 std::string value = value_;
375 }
else if (value_.type() == camp::enumType) {
378 DT_THROW(std::logic_error,
"Unsupported CAMP type=[" << value_.type() <<
"]!");
387 #endif // DATATOOLS_UI_REFLECTIVE_COMMAND_INL_H
#define DT_THROW(ExceptionType, Message)
Definition: exception.h:121
#define DT_LOG_TRACE_EXITING(Priority)
Log a fonction exiting message if Priority is greater or equal to PRIO_TRACE.
Definition: logger_macros.h:267
#define DT_LOG_DEBUG(Priority, Message)
Log Message if Priority is greater or equal to PRIO_DEBUG.
Definition: logger_macros.h:147
#define DT_COMMAND_RETURNED_ERROR(ReturnedInfo, ErrorCode, ErrorMessage)
Definition: command_macros.h:65
#define DT_THROW_IF(Condition, ExceptionType, Message)
Definition: exception.h:76
#define DT_LOG_TRACE(Priority, Message)
Log Message if Priority is greater or equal to PRIO_TRACE.
Definition: logger_macros.h:227
#define DT_LOG_TRACE_ENTERING(Priority)
Log a fonction entering message if Priority is greater or equal to PRIO_TRACE.
Definition: logger_macros.h:261
validators for command line
Description of a method argument.