00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "parser.h"
00024 #include "exceptions.h"
00025
00026 #include <iostream>
00027 #include <vector>
00028
00029 #include <libxml++/libxml++.h>
00030
00031 using namespace std;
00032 using namespace xmlpp;
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 InterfaceParser::InterfaceParser(std::string config_filename)
00045 {
00046 dom = new DomParser();
00047
00048 dom->set_substitute_entities();
00049 dom->parse_file(config_filename);
00050 root = dom->get_document()->get_root_node();
00051 if ( root == NULL ) {
00052 throw InterfaceGeneratorInvalidDocumentException("root == NULL");
00053 }
00054 }
00055
00056
00057
00058 InterfaceParser::~InterfaceParser()
00059 {
00060 delete dom;
00061 }
00062
00063
00064
00065
00066
00067
00068
00069 std::vector<InterfaceField>
00070 InterfaceParser::getFields(xmlpp::Node *node)
00071 {
00072 vector<InterfaceField> result;
00073 NodeSet set = node->find("field");
00074 for (NodeSet::iterator i = set.begin(); i != set.end(); ++i) {
00075
00076 NodeSet nameset = (*i)->find("text()");
00077 if ( nameset.size() == 0 ) {
00078 throw InterfaceGeneratorInvalidContentException("no name for constant");
00079 }
00080 const TextNode *comment_node = dynamic_cast<const TextNode *>(nameset[0]);
00081 if ( ! comment_node ) {
00082 throw InterfaceGeneratorInvalidContentException("comment node not text node for constant");
00083 }
00084 std::string field_comment = comment_node->get_content();
00085
00086
00087
00088 InterfaceField f(&enum_constants);
00089 f.setComment(field_comment);
00090 const Element * el = dynamic_cast<const Element *>(*i);
00091 if ( el ) {
00092
00093 const Element::AttributeList& attrs = el->get_attributes();
00094 for(Element::AttributeList::const_iterator iter = attrs.begin(); iter != attrs.end(); ++iter) {
00095 const Attribute* attr = *iter;
00096
00097 f.setAttribute(attr->get_name(), attr->get_value());
00098 }
00099 } else {
00100 throw InterfaceGeneratorInvalidContentException("constant is not an element");
00101 }
00102
00103 try {
00104 f.valid();
00105 result.push_back(f);
00106 } catch ( fawkes::Exception &e ) {
00107 e.print_trace();
00108 }
00109 }
00110 for (vector<InterfaceField>::iterator i = result.begin(); i != result.end(); ++i) {
00111 for (vector<InterfaceField>::iterator j = i + 1; j != result.end(); ++j) {
00112 if ( (*i).getName() == (*j).getName() ) {
00113 throw InterfaceGeneratorAmbiguousNameException((*i).getName().c_str(), "field");
00114 }
00115 }
00116 }
00117
00118 return result;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128 std::vector<InterfacePseudoMap>
00129 InterfaceParser::getPseudoMaps(xmlpp::Node *node, std::vector<InterfaceField> &fields)
00130 {
00131 vector<InterfacePseudoMap> result;
00132 NodeSet set = node->find("pseudomap");
00133 for (NodeSet::iterator i = set.begin(); i != set.end(); ++i) {
00134 const Element *el = dynamic_cast<const Element *>(*i);
00135 std::string pm_name, pm_type, pm_keytype;
00136
00137 if ( el ) {
00138 Attribute *attr;
00139 attr = el->get_attribute("name");
00140 if ( ! attr ) throw InterfaceGeneratorInvalidContentException("no name for pseudo map");
00141 pm_name = attr->get_value();
00142
00143 attr = el->get_attribute("type");
00144 if ( ! attr ) throw InterfaceGeneratorInvalidContentException("no type for pseudo map");
00145 pm_type = attr->get_value();
00146
00147 attr = el->get_attribute("keytype");
00148 if ( ! attr ) throw InterfaceGeneratorInvalidContentException("no key type for pseudo map");
00149 pm_keytype = attr->get_value();
00150 } else {
00151 throw InterfaceGeneratorInvalidContentException("pseudo map is not an element");
00152 }
00153
00154 NodeSet comment_set = (*i)->find("text()");
00155 if ( comment_set.size() == 0) {
00156 throw InterfaceGeneratorInvalidContentException("pseudo map without comment");
00157 }
00158 std::string pm_comment = "";
00159 const TextNode *comment_node = dynamic_cast<const TextNode *>(comment_set[0]);
00160 if ( comment_node ) {
00161 pm_comment = comment_node->get_content();
00162 } else {
00163 throw InterfaceGeneratorInvalidContentException("pseudo map comment not a text node");
00164 }
00165
00166 InterfacePseudoMap pm(pm_name, pm_type, pm_keytype, pm_comment);
00167
00168 NodeSet ref_nodes = (*i)->find("mapref");
00169 for (NodeSet::iterator r = ref_nodes.begin(); r != ref_nodes.end(); ++r) {
00170 NodeSet ref_set = (*r)->find("text()");
00171 if ( ref_set.size() == 0) {
00172 throw InterfaceGeneratorInvalidContentException("pseudo map without referenced field");
00173 }
00174
00175 const Element *el = dynamic_cast<const Element *>(*r);
00176 Attribute *attr;
00177 attr = el->get_attribute("key");
00178 if ( ! attr ) throw InterfaceGeneratorInvalidContentException("no key for mapref map");
00179 std::string mapref_key = attr->get_value();
00180
00181 const TextNode *text_node = dynamic_cast<const TextNode *>(ref_set[0]);
00182 if ( text_node ) {
00183
00184 bool found = false;
00185 for (vector<InterfaceField>::iterator j = fields.begin(); j != fields.end(); ++j) {
00186 if ( (*j).getName() == text_node->get_content() ) {
00187
00188 if ( j->getLengthValue() > 0 ) {
00189 throw InterfaceGeneratorInvalidContentException("pseudomap references may only point to non-map types");
00190 }
00191 pm.addRef(text_node->get_content(), mapref_key);
00192 found = true;
00193 break;
00194 }
00195 }
00196 if (! found) {
00197 throw InterfaceGeneratorInvalidContentException("reference to non-existing data field");
00198 }
00199
00200 } else {
00201 throw InterfaceGeneratorInvalidContentException("message ref not a text node");
00202 }
00203 }
00204
00205
00206 try {
00207 pm.valid();
00208 result.push_back(pm);
00209 } catch ( fawkes::Exception &e ) {
00210 e.print_trace();
00211 }
00212 }
00213 for (vector<InterfacePseudoMap>::iterator i = result.begin(); i != result.end(); ++i) {
00214 for (vector<InterfacePseudoMap>::iterator j = i + 1; j != result.end(); ++j) {
00215 if ( (*i).getName() == (*j).getName() ) {
00216 throw InterfaceGeneratorAmbiguousNameException((*i).getName().c_str(), "field");
00217 }
00218 }
00219 for (vector<InterfaceField>::iterator f = fields.begin(); f != fields.end(); ++f) {
00220 if ( i->getName() == f->getName() ) {
00221 throw InterfaceGeneratorAmbiguousNameException((*i).getName().c_str(), "pseudo map");
00222 }
00223 }
00224 }
00225
00226 return result;
00227 }
00228
00229
00230
00231
00232
00233
00234 void
00235 InterfaceParser::printFields(vector<InterfaceField> &fields)
00236 {
00237 for (vector<InterfaceField>::iterator i = fields.begin(); i != fields.end(); ++i) {
00238 cout << " Field: name=" << (*i).getName() << " type=" << (*i).getType();
00239 if ( (*i).getLength() != "" ) {
00240 cout << " length=" << (*i).getLength();
00241 }
00242 if ( (*i).getValidFor() != "" ) {
00243 cout << " validfor=" << (*i).getValidFor();
00244 }
00245 if ( (*i).getDefaultValue() != "" ) {
00246 cout << " default=" << (*i).getDefaultValue();
00247 }
00248 vector<string> flags = (*i).getFlags();
00249 if ( flags.size() > 0 ) {
00250 cout << " flags=";
00251 vector<string>::iterator j = flags.begin();
00252 while (j != flags.end()) {
00253 cout << *j;
00254 ++j;
00255 if ( j != flags.end()) {
00256 cout << ",";
00257 }
00258 }
00259 }
00260 cout << endl;
00261 }
00262 }
00263
00264
00265
00266
00267 void
00268 InterfaceParser::printPseudoMaps(vector<InterfacePseudoMap> &pseudo_maps)
00269 {
00270 for (vector<InterfacePseudoMap>::iterator i = pseudo_maps.begin(); i != pseudo_maps.end(); ++i) {
00271 cout << " PseudoMap: name=" << i->getName()
00272 << " type=" << i->getType()
00273 << " keytype=" << i->getKeyType() << endl;
00274 InterfacePseudoMap::RefList &reflist = i->getRefList();
00275
00276 InterfacePseudoMap::RefList::iterator i;
00277 for (i = reflist.begin(); i != reflist.end(); ++i) {
00278 cout << " Ref: field=" << i->first
00279 << " key=" << i->second << endl;
00280 }
00281
00282 cout << endl;
00283 }
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 void
00295 InterfaceParser::printParsed(vector<InterfaceConstant> & constants,
00296 vector<InterfaceEnumConstant> & enum_constants,
00297 vector<InterfaceField> & data_fields,
00298 vector<InterfacePseudoMap> & pseudo_maps,
00299 vector<InterfaceMessage> & messages)
00300 {
00301 cout << "Constants" << endl;
00302 for (vector<InterfaceConstant>::iterator i = constants.begin(); i != constants.end(); ++i) {
00303 cout << " Constant: name=" << (*i).getName() << " type=" << (*i).getType()
00304 << " value=" << (*i).getValue() << endl;
00305 }
00306
00307 cout << "EnumConstants" << endl;
00308 for (vector<InterfaceEnumConstant>::iterator i = enum_constants.begin(); i != enum_constants.end(); ++i) {
00309 cout << " EnumConstant: name=" << (*i).getName() << endl;
00310 vector< pair<string,string> > items = (*i).getItems();
00311 for (vector< pair<string,string> >::iterator j = items.begin(); j != items.end(); ++j) {
00312 cout << " Item: " << (*j).first << "(" << (*j).second << ")" << endl;
00313 }
00314 }
00315
00316 cout << "Data block" << endl;
00317 printFields(data_fields);
00318 printPseudoMaps(pseudo_maps);
00319 for (vector<InterfaceMessage>::iterator i = messages.begin(); i != messages.end(); ++i) {
00320 cout << "Message: name=" << (*i).getName() << endl;
00321 vector<InterfaceField> msg_fields = (*i).getFields();
00322 printFields(msg_fields);
00323 }
00324 }
00325
00326
00327
00328 void
00329 InterfaceParser::print()
00330 {
00331 printParsed(constants, enum_constants, data_fields, pseudo_maps, messages);
00332 }
00333
00334
00335
00336 void
00337 InterfaceParser::parse()
00338 {
00339 NodeSet set;
00340
00341 constants.clear();
00342 enum_constants.clear();
00343 data_fields.clear();
00344 messages.clear();
00345
00346
00347
00348
00349
00350 const Element * el = dynamic_cast<const Element *>(root);
00351 if ( el ) {
00352
00353 Attribute *attr;
00354 attr = el->get_attribute("name");
00355 if ( ! attr ) {
00356 throw InterfaceGeneratorInvalidContentException("no name for interface");
00357 }
00358 name = attr->get_value();
00359
00360 attr = el->get_attribute("author");
00361 if ( attr ) {
00362 author = attr->get_value();
00363 }
00364 attr = el->get_attribute("year");
00365 if ( attr ) {
00366 year = attr->get_value();
00367 }
00368 attr = el->get_attribute("created");
00369 if ( attr ) {
00370 creation_date = attr->get_value();
00371 }
00372 } else {
00373 throw InterfaceGeneratorInvalidContentException("root is not an element");
00374 }
00375
00376
00377
00378
00379
00380 NodeSet constants_set = root->find("/interface/constants");
00381 if ( constants_set.size() > 1 ) {
00382 throw InterfaceGeneratorInvalidContentException("more than one constants block");
00383 }
00384 if ( constants_set.size() == 1 ) {
00385
00386 set = constants_set[0]->find("constant");
00387 for (NodeSet::iterator i = set.begin(); i != set.end(); ++i) {
00388
00389
00390 NodeSet nameset = (*i)->find("text()");
00391 if ( nameset.size() == 0 ) {
00392 throw InterfaceGeneratorInvalidContentException("no name for constant");
00393 }
00394 const TextNode *comment_node = dynamic_cast<const TextNode *>(nameset[0]);
00395 if ( ! comment_node ) {
00396 throw InterfaceGeneratorInvalidContentException("name node not text node for constant");
00397 }
00398 std::string const_comment = comment_node->get_content();
00399
00400
00401
00402 std::string type;
00403 std::string value;
00404 std::string const_name;
00405
00406 el = dynamic_cast<const Element *>(*i);
00407 if ( el ) {
00408
00409 Attribute *attr;
00410 attr = el->get_attribute("type");
00411 if ( ! attr ) {
00412 throw InterfaceGeneratorInvalidContentException("no type for constant");
00413 }
00414 type = attr->get_value();
00415
00416 attr = el->get_attribute("name");
00417 if ( ! attr ) {
00418 throw InterfaceGeneratorInvalidContentException("no name for constant");
00419 }
00420 const_name = attr->get_value();
00421
00422 attr = el->get_attribute("value");
00423 if ( ! attr ) {
00424 throw InterfaceGeneratorInvalidContentException("no value for constant");
00425 }
00426 value = attr->get_value();
00427 } else {
00428 throw InterfaceGeneratorInvalidContentException("constant is not an element");
00429 }
00430
00431
00432 try {
00433 InterfaceConstant constant(const_name, type, value, const_comment);
00434 constants.push_back(constant);
00435 } catch (InterfaceGeneratorInvalidTypeException &e) {
00436 e.print_trace();
00437 } catch (InterfaceGeneratorInvalidValueException &e) {
00438 e.print_trace();
00439 }
00440 }
00441 for (vector<InterfaceConstant>::iterator i = constants.begin(); i != constants.end(); ++i) {
00442 for (vector<InterfaceConstant>::iterator j = i + 1; j != constants.end(); ++j) {
00443 if ( (*i).getName() == (*j).getName() ) {
00444 throw InterfaceGeneratorAmbiguousNameException((*i).getName().c_str(), "constant");
00445 }
00446 }
00447 }
00448
00449
00450
00451
00452
00453 set = constants_set[0]->find("enum");
00454 for (NodeSet::iterator i = set.begin(); i != set.end(); ++i) {
00455
00456 std::string enum_comment;
00457 NodeSet comment_set = (*i)->find("comment/text()");
00458 if ( comment_set.size() == 0 ) {
00459 throw InterfaceGeneratorInvalidContentException("no comment for enum");
00460 } else {
00461 const TextNode *comment_node = dynamic_cast<const TextNode *>(comment_set[0]);
00462 if ( comment_node ) {
00463 enum_comment = comment_node->get_content();
00464 } else {
00465 throw InterfaceGeneratorInvalidContentException("enum comment not a text node");
00466 }
00467 }
00468
00469 string enum_name;
00470 el = dynamic_cast<const Element *>(*i);
00471 if ( el ) {
00472
00473 Attribute *attr;
00474 attr = el->get_attribute("name");
00475 if ( ! attr ) {
00476 throw InterfaceGeneratorInvalidContentException("no name for enum");
00477 }
00478 enum_name = attr->get_value();
00479
00480 } else {
00481 throw InterfaceGeneratorInvalidContentException("enum is not an element");
00482 }
00483
00484 InterfaceEnumConstant enum_constant(enum_name, enum_comment);
00485
00486
00487 NodeSet items = (*i)->find("item");
00488 if ( items.size() == 0 ) {
00489 throw InterfaceGeneratorInvalidContentException("no items for enum");
00490 }
00491
00492 for (NodeSet::iterator j = items.begin(); j != items.end(); ++j) {
00493
00494 std::string item_name;
00495 el = dynamic_cast<const Element *>(*j);
00496 if ( el ) {
00497
00498 Attribute *attr;
00499 attr = el->get_attribute("name");
00500 if ( ! attr ) {
00501 throw InterfaceGeneratorInvalidContentException("no name for enum item");
00502 }
00503 item_name = attr->get_value();
00504
00505 } else {
00506 throw InterfaceGeneratorInvalidContentException("enum item is not an element");
00507 }
00508
00509 comment_set = (*j)->find("text()");
00510 if ( comment_set.size() == 0) {
00511 throw InterfaceGeneratorInvalidContentException("enum item without comment");
00512 }
00513 const TextNode *comment_node = dynamic_cast<const TextNode *>(comment_set[0]);
00514 if ( comment_node ) {
00515 enum_constant.addItem(item_name, comment_node->get_content());
00516 } else {
00517 throw InterfaceGeneratorInvalidContentException("enum comment not a text node");
00518 }
00519 }
00520
00521 enum_constants.push_back(enum_constant);
00522 }
00523 for (vector<InterfaceEnumConstant>::iterator i = enum_constants.begin(); i != enum_constants.end(); ++i) {
00524 for (vector<InterfaceEnumConstant>::iterator j = i + 1; j != enum_constants.end(); ++j) {
00525 if ( (*i).getName() == (*j).getName() ) {
00526 throw InterfaceGeneratorAmbiguousNameException((*i).getName().c_str(), "enum constant");
00527 }
00528 }
00529 }
00530 }
00531
00532
00533
00534
00535
00536 set = root->find("/interface/data");
00537 if ( set.size() > 1 ) {
00538 throw InterfaceGeneratorInvalidContentException("more than one data block");
00539 } else if ( set.size() == 0 ) {
00540 throw InterfaceGeneratorInvalidContentException("no data block");
00541 }
00542
00543 data_fields = getFields(set[0]);
00544 if ( data_fields.size() == 0 ) {
00545 throw InterfaceGeneratorInvalidContentException("data block contains no field");
00546 }
00547
00548 pseudo_maps = getPseudoMaps(set[0], data_fields);
00549
00550 NodeSet comment_set = root->find("/interface/data/comment/text()");
00551 if ( comment_set.size() == 0) {
00552 throw InterfaceGeneratorInvalidContentException("data block without comment");
00553 }
00554 const TextNode *comment_node = dynamic_cast<const TextNode *>(comment_set[0]);
00555 if ( comment_node ) {
00556 data_comment = comment_node->get_content();
00557 } else {
00558 throw InterfaceGeneratorInvalidContentException("data block comment not a text node");
00559 }
00560
00561
00562
00563
00564
00565 set = root->find("/interface/message");
00566 for (NodeSet::iterator i = set.begin(); i != set.end(); ++i) {
00567 std::string msg_name;
00568 std::string msg_comment;
00569
00570 el = dynamic_cast<const Element *>(*i);
00571 if ( el ) {
00572 Attribute *attr;
00573 attr = el->get_attribute("name");
00574 if ( ! attr ) {
00575 throw InterfaceGeneratorInvalidContentException("no name for message");
00576 }
00577 msg_name = attr->get_value();
00578 } else {
00579 throw InterfaceGeneratorInvalidContentException("message is not an element");
00580 }
00581
00582 comment_set = (*i)->find("text()");
00583 if ( comment_set.size() == 0) {
00584 throw InterfaceGeneratorInvalidContentException("message without comment");
00585 }
00586 comment_node = dynamic_cast<const TextNode *>(comment_set[0]);
00587 if ( comment_node ) {
00588 msg_comment = comment_node->get_content();
00589 } else {
00590 throw InterfaceGeneratorInvalidContentException("message comment not a text node");
00591 }
00592
00593
00594 vector<InterfaceField> msg_fields = getFields(*i);
00595
00596 NodeSet ref_nodes = (*i)->find("ref/text()");
00597 for (NodeSet::iterator r = ref_nodes.begin(); r != ref_nodes.end(); ++r) {
00598 const TextNode *text_node = dynamic_cast<const TextNode *>(*r);
00599 if ( text_node ) {
00600
00601 bool found = false;
00602 for (vector<InterfaceField>::iterator j = data_fields.begin(); j != data_fields.end(); ++j) {
00603 if ( (*j).getName() == text_node->get_content() ) {
00604
00605 msg_fields.push_back(*j);
00606 found = true;
00607 break;
00608 }
00609 }
00610 if (! found) {
00611 throw InterfaceGeneratorInvalidContentException("reference to non-existing data field");
00612 }
00613 } else {
00614 throw InterfaceGeneratorInvalidContentException("message ref not a text node");
00615 }
00616 }
00617 for (vector<InterfaceField>::iterator k = msg_fields.begin(); k != msg_fields.end(); ++k) {
00618 for (vector<InterfaceField>::iterator j = k + 1; j != msg_fields.end(); ++j) {
00619 if ( (*k).getName() == (*j).getName() ) {
00620 throw InterfaceGeneratorAmbiguousNameException((*k).getName().c_str(), "message field");
00621 }
00622 }
00623 }
00624
00625 InterfaceMessage msg(msg_name, msg_comment);
00626 msg.setFields(msg_fields);
00627
00628 messages.push_back(msg);
00629 }
00630
00631 }
00632
00633
00634
00635
00636
00637
00638 std::string
00639 InterfaceParser::getInterfaceName()
00640 {
00641 return name;
00642 }
00643
00644
00645
00646
00647
00648
00649 std::string
00650 InterfaceParser::getInterfaceAuthor()
00651 {
00652 return author;
00653 }
00654
00655
00656
00657
00658
00659
00660 std::string
00661 InterfaceParser::getInterfaceYear()
00662 {
00663 return year;
00664 }
00665
00666
00667
00668
00669
00670
00671 std::string
00672 InterfaceParser::getInterfaceCreationDate()
00673 {
00674 return creation_date;
00675 }
00676
00677
00678
00679
00680
00681
00682 std::vector<InterfaceConstant>
00683 InterfaceParser::getConstants()
00684 {
00685 return constants;
00686 }
00687
00688
00689
00690
00691
00692
00693 std::vector<InterfaceEnumConstant>
00694 InterfaceParser::getEnumConstants()
00695 {
00696 return enum_constants;
00697 }
00698
00699
00700
00701
00702
00703
00704 std::vector<InterfaceField>
00705 InterfaceParser::getDataFields()
00706 {
00707 return data_fields;
00708 }
00709
00710
00711
00712
00713
00714
00715 std::vector<InterfacePseudoMap>
00716 InterfaceParser::getPseudoMaps()
00717 {
00718 return pseudo_maps;
00719 }
00720
00721
00722
00723
00724
00725
00726 std::string
00727 InterfaceParser::getDataComment()
00728 {
00729 return data_comment;
00730 }
00731
00732
00733
00734
00735
00736
00737 std::vector<InterfaceMessage>
00738 InterfaceParser::getMessages()
00739 {
00740 return messages;
00741 }