00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <opspace/parse_yaml.hpp>
00023 #include <opspace/Factory.hpp>
00024 #include <opspace/Task.hpp>
00025 #include <opspace/Skill.hpp>
00026 #include <stdexcept>
00027
00028 using jspace::pretty_print;
00029 using boost::shared_ptr;
00030 using std::string;
00031
00032
00033 namespace opspace {
00034
00035
00036 Parser::
00037 Parser(Factory const & factory_, std::ostream * optional_dbg_os)
00038 : factory(factory_),
00039 dbg(optional_dbg_os)
00040 {
00041 }
00042
00043
00044 Parser::
00045 ~Parser()
00046 {
00047 }
00048
00049
00050 TaskParser::
00051 TaskParser(Factory const & factory, std::ostream * optional_dbg_os)
00052 : Parser(factory, optional_dbg_os),
00053 type("void"),
00054 name(""),
00055 task(0)
00056 {
00057 }
00058
00059
00060 SkillParser::
00061 SkillParser(Factory const & factory, std::ostream * optional_dbg_os)
00062 : Parser(factory, optional_dbg_os),
00063 type("void"),
00064 name(""),
00065 skill(0)
00066 {
00067 }
00068
00069
00070 TaskTableParser::
00071 TaskTableParser(Factory const & factory,
00072 Factory::task_table_t & task_table_,
00073 std::ostream * optional_dbg_os)
00074 : Parser(factory, optional_dbg_os),
00075 task_parser(factory, optional_dbg_os),
00076 task_table(task_table_)
00077 {
00078 }
00079
00080
00081 SkillTableParser::
00082 SkillTableParser(Factory const & factory,
00083 Factory::skill_table_t & skill_table_,
00084 std::ostream * optional_dbg_os)
00085 : Parser(factory, optional_dbg_os),
00086 skill_parser(factory, optional_dbg_os),
00087 skill_table(skill_table_)
00088 {
00089 }
00090
00091
00092 static char const * yaml_type_name(YAML::Node const & node)
00093 {
00094 switch (node.GetType()) {
00095 case YAML::CT_NONE:
00096 return "NONE";
00097 case YAML::CT_SCALAR:
00098 return "SCALAR";
00099 case YAML::CT_SEQUENCE:
00100 return "SEQUENCE";
00101 case YAML::CT_MAP:
00102 return "MAP";
00103 }
00104 return "unknown";
00105 }
00106
00107
00108 void operator >> (YAML::Node const & node, Vector & vector)
00109 {
00110 vector.resize(node.size());
00111 for (size_t ii(0); ii < node.size(); ++ii) {
00112 node[ii] >> vector.coeffRef(ii);
00113 }
00114 }
00115
00116
00117 static Parameter * parse_parameter(std::string const & com_type,
00118 std::string const & com_name,
00119 ParameterReflection & pr,
00120 std::string const & key,
00121 YAML::Node const & value)
00122 throw(std::runtime_error)
00123 {
00124 Parameter * param(pr.lookupParameter(key));
00125 if ( ! param) {
00126 throw std::runtime_error("no parameter called `" + key + "' in " + com_type
00127 + " `" + com_name + "'");
00128 }
00129
00130 if (PARAMETER_TYPE_INTEGER == param->type_) {
00131 if (YAML::CT_SCALAR != value.GetType()) {
00132 throw std::runtime_error("parameter `" + key
00133 + "' of " + com_type + " `" + com_name
00134 + "' should be scalar (integer) but is "
00135 + string(yaml_type_name(value)));
00136 }
00137 int integer;
00138 value >> integer;
00139 Status const st(param->set(integer));
00140 if ( ! st) {
00141 throw std::runtime_error("setting integer parameter `" + key
00142 + "' of " + com_type + " `" + com_name
00143 + "' failed: " + st.errstr);
00144 }
00145 }
00146
00147 else if (PARAMETER_TYPE_STRING == param->type_) {
00148 if (YAML::CT_SCALAR != value.GetType()) {
00149 throw std::runtime_error("parameter `" + key
00150 + "' of " + com_type + " `" + com_name
00151 + "' should be scalar (string) but is "
00152 + string(yaml_type_name(value)));
00153 }
00154 std::string foo;
00155 value >> foo;
00156 Status const st(param->set(foo));
00157 if ( ! st) {
00158 throw std::runtime_error("setting string parameter `" + key
00159 + "' of " + com_type + " `" + com_name
00160 + "' failed: " + st.errstr);
00161 }
00162 }
00163
00164 else if (PARAMETER_TYPE_REAL == param->type_) {
00165 if (YAML::CT_SCALAR != value.GetType()) {
00166 throw std::runtime_error("parameter `" + key
00167 + "' of " + com_type + " `" + com_name
00168 + "' should be scalar (real) but is "
00169 + string(yaml_type_name(value)));
00170 }
00171 double real;
00172 value >> real;
00173 Status const st(param->set(real));
00174 if ( ! st) {
00175 throw std::runtime_error("setting real parameter `" + key
00176 + "' of " + com_type + " `" + com_name
00177 + "' failed: " + st.errstr);
00178 }
00179 }
00180
00181 else if (PARAMETER_TYPE_VECTOR == param->type_) {
00182 if (YAML::CT_SEQUENCE != value.GetType()) {
00183 throw std::runtime_error("parameter `" + key
00184 + "' of " + com_type + " `" + com_name
00185 + "' should be sequence (vector) but is "
00186 + string(yaml_type_name(value)));
00187 }
00188 Vector vector;
00189 value >> vector;
00190 Status const st(param->set(vector));
00191 if ( ! st) {
00192 throw std::runtime_error("setting vector parameter `" + key
00193 + "' of " + com_type + " `" + com_name
00194 + "' failed: " + st.errstr);
00195 }
00196 }
00197
00198 else if (PARAMETER_TYPE_MATRIX == param->type_) {
00199 throw std::runtime_error("setting parameter `" + key
00200 + "' of " + com_type + " `" + com_name
00201 + "' requires MATRIX type which is not (yet) supported");
00202 }
00203
00204 else {
00205 throw std::runtime_error("setting parameter `" + key
00206 + "' of " + com_type + " `" + com_name
00207 + "' invalid or VOID type (need to update parse_yaml.cpp maybe?)");
00208 }
00209
00210 return param;
00211 }
00212
00213
00214 void operator >> (YAML::Node const & node, TaskParser & parser)
00215 {
00216 parser.task = 0;
00217 if (parser.dbg) {
00218 *parser.dbg << "DEBUG opspace::operator>>(YAML::Node &, task_parser_s &)\n"
00219 << " reading type and name\n";
00220 }
00221 node["type"] >> parser.type;
00222 node["name"] >> parser.name;
00223
00224 if (parser.dbg) {
00225 *parser.dbg << " type = " << parser.type << " name = " << parser.name << "\n";
00226 }
00227 parser.task = Factory::createTask(parser.type, parser.name);
00228 if ( ! parser.task) {
00229 throw std::runtime_error("createTask(`" + parser.type + "', `" + parser.name + "') failed");
00230 }
00231
00232 if (parser.dbg) {
00233 *parser.dbg << " created task `" << parser.name << "' of type " << parser.type << "\n"
00234 << " parsing parameters:\n";
00235 }
00236 for (YAML::Iterator it(node.begin()); it != node.end(); ++it) {
00237 std::string key;
00238 it.first() >> key;
00239 if (("type" == key) || ("name" == key)) {
00240 continue;
00241 }
00242 YAML::Node const & value(it.second());
00243
00244 if (parser.dbg) {
00245 *parser.dbg << " trying `" << key << "' (YAML type " << yaml_type_name(value) << ")\n";
00246 }
00247
00248 Parameter const * param(parse_parameter("task", parser.name, *parser.task, key, value));
00249 if (parser.dbg) {
00250 param->dump(*parser.dbg, " ");
00251 }
00252
00253 }
00254 }
00255
00256
00257 void operator >> (YAML::Node const & node, SkillParser & parser)
00258 {
00259 parser.skill = 0;
00260 if (parser.dbg) {
00261 *parser.dbg << "DEBUG opspace::operator>>(YAML::Node &, skill_parser_s &)\n"
00262 << " reading type and name\n";
00263 }
00264 node["type"] >> parser.type;
00265 node["name"] >> parser.name;
00266
00267 if (parser.dbg) {
00268 *parser.dbg << " type = " << parser.type << " name = " << parser.name << "\n";
00269 }
00270 parser.skill = Factory::createSkill(parser.type, parser.name);
00271 if ( ! parser.skill) {
00272 throw std::runtime_error("createSkill(`" + parser.type + "', `" + parser.name + "') failed");
00273 }
00274
00275 if (parser.dbg) {
00276 *parser.dbg << " created skill `" << parser.name
00277 << "' of type " << parser.type << "\n"
00278 << " parsing slots and parameters:\n";
00279 }
00280 for (YAML::Iterator it(node.begin()); it != node.end(); ++it) {
00281 std::string key;
00282 it.first() >> key;
00283 if (("type" == key) || ("name" == key)) {
00284 continue;
00285 }
00286
00287 if ("slots" == key) {
00288 YAML::Node const & slotlist(it.second());
00289 for (YAML::Iterator slot_it(slotlist.begin()); slot_it != slotlist.end(); ++slot_it) {
00290 std::string slot_name;
00291 std::string task_name;
00292
00293 if (YAML::CT_MAP == slotlist.GetType()) {
00294 slot_it.first() >> slot_name;
00295 slot_it.second() >> task_name;
00296 }
00297 else if (YAML::CT_SEQUENCE == slotlist.GetType()) {
00298 if (YAML::CT_MAP != slot_it->GetType()) {
00299 throw std::runtime_error("list item for `" + key + "' is a "
00300 + string(yaml_type_name(slotlist))
00301 + " but should be a map with one key/value pair");
00302 }
00303 YAML::Iterator slot_it_it(slot_it->begin());
00304 if (slot_it->end() == slot_it_it) {
00305 throw std::runtime_error("list item for `" + key
00306 + "' is empty but should have one key/value pair");
00307 }
00308 slot_it_it.first() >> slot_name;
00309 slot_it_it.second() >> task_name;
00310 ++slot_it_it;
00311 if (slot_it->end() != slot_it_it) {
00312 throw std::runtime_error("list item for `" + key
00313 + "' has more than one key/value pair");
00314 }
00315 }
00316 else {
00317 throw std::runtime_error("entry for `" + key + "' is a "
00318 + string(yaml_type_name(slotlist))
00319 + " but should be a map or a list");
00320 }
00321
00322 shared_ptr<TaskSlotAPI> slot(parser.skill->lookupSlot(slot_name));
00323 if ( ! slot) {
00324 throw std::runtime_error("skill `" + parser.name + "' has no slot `"
00325 + slot_name + "'");
00326 }
00327
00328 shared_ptr<Task> task(parser.factory.findTask(task_name));
00329 if ( ! task) {
00330 throw std::runtime_error("no task instance `" + task_name + "' for skill `"
00331 + parser.name + "' slot `" + slot_name + "'");
00332 }
00333
00334 Status const st(slot->assign(task));
00335 if ( ! st) {
00336 throw std::runtime_error("oops assigning task instance `" + task_name
00337 + "' to skill `" + parser.name
00338 + "' slot `" + slot_name + "': " + st.errstr);
00339 }
00340
00341 if (parser.dbg) {
00342 *parser.dbg << " assigned task instance `" << task_name
00343 << "' to slot `" << slot_name << "' in skill `"
00344 << parser.name << "'\n";
00345 }
00346 }
00347 }
00348
00349 else {
00350
00351 Parameter const * param(parse_parameter("skill", parser.name,
00352 *parser.skill, key, it.second()));
00353 if (parser.dbg) {
00354 param->dump(*parser.dbg, " ");
00355 }
00356 }
00357
00358 }
00359 }
00360
00361
00362 void operator >> (YAML::Node const & node, TaskTableParser & parser)
00363 {
00364 for (size_t ii(0); ii < node.size(); ++ii) {
00365 YAML::Node const & entry(node[ii]);
00366 entry >> parser.task_parser;
00367 if ( ! parser.task_parser.task) {
00368 throw std::runtime_error("failed to create task instance");
00369 }
00370 parser.task_table.push_back(shared_ptr<Task>(parser.task_parser.task));
00371 }
00372 }
00373
00374
00375 void operator >> (YAML::Node const & node, SkillTableParser & parser)
00376 {
00377 if (parser.dbg) {
00378 *parser.dbg << "DEBUG opspace::operator>>(YAML::Node &, SkillTableParser &)\n"
00379 << " parsing " << node.size() << " nodes\n";
00380 }
00381 for (size_t ii(0); ii < node.size(); ++ii) {
00382 YAML::Node const & entry(node[ii]);
00383 entry >> parser.skill_parser;
00384 if ( ! parser.skill_parser.skill) {
00385 throw std::runtime_error("failed to create skill instance");
00386 }
00387 if (parser.dbg) {
00388 parser.skill_parser.skill->dump(*parser.dbg, " adding to table: skill", " ");
00389 }
00390 parser.skill_table.push_back(shared_ptr<Skill>(parser.skill_parser.skill));
00391 }
00392 }
00393
00394 }