SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00010 // A storage for options (typed value containers) 00011 /****************************************************************************/ 00012 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00013 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00014 /****************************************************************************/ 00015 // 00016 // This file is part of SUMO. 00017 // SUMO is free software: you can redistribute it and/or modify 00018 // it under the terms of the GNU General Public License as published by 00019 // the Free Software Foundation, either version 3 of the License, or 00020 // (at your option) any later version. 00021 // 00022 /****************************************************************************/ 00023 // =========================================================================== 00024 // included modules 00025 // =========================================================================== 00026 #ifdef _MSC_VER 00027 #include <windows_config.h> 00028 #else 00029 #include <config.h> 00030 #endif 00031 00032 #include <map> 00033 #include <string> 00034 #include <exception> 00035 #include <algorithm> 00036 #include <vector> 00037 #include <iostream> 00038 #include <cstdlib> 00039 #include <cassert> 00040 #include <ctime> 00041 #include <iterator> 00042 #include "Option.h" 00043 #include "OptionsCont.h" 00044 #include <utils/common/UtilExceptions.h> 00045 #include <utils/common/FileHelpers.h> 00046 #include <utils/common/MsgHandler.h> 00047 #include <utils/common/StringTokenizer.h> 00048 #include <utils/common/StringUtils.h> 00049 #include <utils/xml/SUMOSAXAttributes.h> 00050 #include <sstream> 00051 00052 #ifdef CHECK_MEMORY_LEAKS 00053 #include <foreign/nvwa/debug_new.h> 00054 #endif // CHECK_MEMORY_LEAKS 00055 00056 00057 // =========================================================================== 00058 // static member definitions 00059 // =========================================================================== 00060 OptionsCont OptionsCont::myOptions; 00061 00062 00063 // =========================================================================== 00064 // method definitions 00065 // =========================================================================== 00066 OptionsCont& 00067 OptionsCont::getOptions() { 00068 return myOptions; 00069 } 00070 00071 00072 OptionsCont::OptionsCont() 00073 : myAddresses(), myValues(), myDeprecatedSynonymes(), myHaveInformedAboutDeprecatedDivider(false) { 00074 myCopyrightNotices.push_back("Copyright (C) 2001-2012 DLR and contributors; http://sumo.sourceforge.net"); 00075 } 00076 00077 00078 OptionsCont::~OptionsCont() { 00079 clear(); 00080 } 00081 00082 00083 void 00084 OptionsCont::doRegister(const std::string& name, Option* v) { 00085 assert(v != 0); 00086 ItemAddressContType::iterator i = find(myAddresses.begin(), myAddresses.end(), v); 00087 if (i == myAddresses.end()) { 00088 myAddresses.push_back(v); 00089 } 00090 if (myValues.find(name) != myValues.end()) { 00091 throw ProcessError(name + " is an already used option name."); 00092 } 00093 myValues[name] = v; 00094 } 00095 00096 00097 void 00098 OptionsCont::doRegister(const std::string& name1, char abbr, Option* v) { 00099 doRegister(name1, v); 00100 doRegister(convertChar(abbr), v); 00101 } 00102 00103 00104 void 00105 OptionsCont::addSynonyme(const std::string& name1, const std::string& name2, bool isDeprecated) { 00106 KnownContType::iterator i1 = myValues.find(name1); 00107 KnownContType::iterator i2 = myValues.find(name2); 00108 if (i1 == myValues.end() && i2 == myValues.end()) { 00109 throw ProcessError("Neither the option '" + name1 + "' nor the option '" + name2 + "' is known yet"); 00110 } 00111 if (i1 != myValues.end() && i2 != myValues.end()) { 00112 if ((*i1).second == (*i2).second) { 00113 return; 00114 } 00115 throw ProcessError("Both options '" + name1 + "' and '" + name2 + "' do exist and differ."); 00116 } 00117 if (i1 == myValues.end() && i2 != myValues.end()) { 00118 doRegister(name1, (*i2).second); 00119 if (isDeprecated) { 00120 myDeprecatedSynonymes[name1] = false; 00121 } 00122 } 00123 if (i1 != myValues.end() && i2 == myValues.end()) { 00124 doRegister(name2, (*i1).second); 00125 if (isDeprecated) { 00126 myDeprecatedSynonymes[name2] = false; 00127 } 00128 } 00129 } 00130 00131 00132 bool 00133 OptionsCont::exists(const std::string& name) const { 00134 return myValues.count(name) > 0; 00135 } 00136 00137 00138 bool 00139 OptionsCont::isSet(const std::string& name, bool failOnNonExistant) const { 00140 KnownContType::const_iterator i = myValues.find(name); 00141 if (i == myValues.end()) { 00142 if (failOnNonExistant) { 00143 throw ProcessError("Internal request for unknown option '" + name + "'!"); 00144 } else { 00145 return false; 00146 } 00147 } 00148 return (*i).second->isSet(); 00149 } 00150 00151 00152 bool 00153 OptionsCont::isDefault(const std::string& name) const { 00154 KnownContType::const_iterator i = myValues.find(name); 00155 if (i == myValues.end()) { 00156 return false; 00157 } 00158 return (*i).second->isDefault(); 00159 } 00160 00161 00162 Option* 00163 OptionsCont::getSecure(const std::string& name) const { 00164 KnownContType::const_iterator k = myValues.find(name); 00165 if (k == myValues.end()) { 00166 throw ProcessError("No option with the name '" + name + "' exists."); 00167 } 00168 std::map<std::string, bool>::iterator s = myDeprecatedSynonymes.find(name); 00169 if (s != myDeprecatedSynonymes.end() && !s->second) { 00170 std::string defaultName; 00171 for (std::map<std::string, std::vector<std::string> >::const_iterator i = mySubTopicEntries.begin(); i != mySubTopicEntries.end(); ++i) { 00172 for (std::vector<std::string>::const_iterator j = i->second.begin(); j != i->second.end(); ++j) { 00173 KnownContType::const_iterator l = myValues.find(*j); 00174 if (l != myValues.end() && l->second == k->second) { 00175 defaultName = *j; 00176 break; 00177 } 00178 } 00179 if (defaultName != "") { 00180 break; 00181 } 00182 } 00183 WRITE_WARNING("Please note that '" + name + "' is deprecated.\n Use '" + defaultName + "' instead."); 00184 s->second = true; 00185 } 00186 return k->second; 00187 } 00188 00189 00190 std::string 00191 OptionsCont::getString(const std::string& name) const { 00192 Option* o = getSecure(name); 00193 return o->getString(); 00194 } 00195 00196 00197 SUMOReal 00198 OptionsCont::getFloat(const std::string& name) const { 00199 Option* o = getSecure(name); 00200 return o->getFloat(); 00201 } 00202 00203 00204 int 00205 OptionsCont::getInt(const std::string& name) const { 00206 Option* o = getSecure(name); 00207 return o->getInt(); 00208 } 00209 00210 00211 bool 00212 OptionsCont::getBool(const std::string& name) const { 00213 Option* o = getSecure(name); 00214 return o->getBool(); 00215 } 00216 00217 00218 const IntVector& 00219 OptionsCont::getIntVector(const std::string& name) const { 00220 Option* o = getSecure(name); 00221 return o->getIntVector(); 00222 } 00223 00224 00225 bool 00226 OptionsCont::set(const std::string& name, const std::string& value) { 00227 Option* o = getSecure(name); 00228 if (!o->isWriteable()) { 00229 reportDoubleSetting(name); 00230 return false; 00231 } 00232 try { 00233 if (!o->set(value)) { 00234 return false; 00235 } 00236 } catch (ProcessError& e) { 00237 WRITE_ERROR("While processing option '" + name + "':\n " + e.what()); 00238 return false; 00239 } 00240 return true; 00241 } 00242 00243 00244 std::vector<std::string> 00245 OptionsCont::getSynonymes(const std::string& name) const { 00246 Option* o = getSecure(name); 00247 std::vector<std::string> v(0); 00248 for (KnownContType::const_iterator i = myValues.begin(); i != myValues.end(); i++) { 00249 if ((*i).second == o && name != (*i).first) { 00250 v.push_back((*i).first); 00251 } 00252 } 00253 return v; 00254 } 00255 00256 00257 std::ostream& 00258 operator<<(std::ostream& os, const OptionsCont& oc) { 00259 std::vector<std::string> done; 00260 os << "Options set:" << std::endl; 00261 for (OptionsCont::KnownContType::const_iterator i = oc.myValues.begin(); 00262 i != oc.myValues.end(); i++) { 00263 std::vector<std::string>::iterator j = find(done.begin(), done.end(), (*i).first); 00264 if (j == done.end()) { 00265 std::vector<std::string> synonymes = oc.getSynonymes((*i).first); 00266 if (synonymes.size() != 0) { 00267 os << (*i).first << " ("; 00268 for (j = synonymes.begin(); j != synonymes.end(); j++) { 00269 if (j != synonymes.begin()) { 00270 os << ", "; 00271 } 00272 os << (*j); 00273 } 00274 os << ")"; 00275 } else { 00276 os << (*i).first; 00277 } 00278 if ((*i).second->isSet()) { 00279 os << ": " << (*i).second->getValueString() << std::endl; 00280 } else { 00281 os << ": <INVALID>" << std::endl; 00282 } 00283 done.push_back((*i).first); 00284 copy(synonymes.begin(), synonymes.end(), back_inserter(done)); 00285 } 00286 } 00287 return os; 00288 } 00289 00290 00291 void 00292 OptionsCont::relocateFiles(const std::string& configuration) const { 00293 for (ItemAddressContType::const_iterator i = myAddresses.begin(); i != myAddresses.end(); i++) { 00294 if ((*i)->isFileName() && (*i)->isSet()) { 00295 StringTokenizer st((*i)->getString(), ";, ", true); 00296 std::string conv; 00297 while (st.hasNext()) { 00298 if (conv.length() != 0) { 00299 conv += ','; 00300 } 00301 std::string tmp = st.next(); 00302 if (!FileHelpers::isAbsolute(tmp)) { 00303 tmp = FileHelpers::getConfigurationRelative(configuration, tmp); 00304 } 00305 conv += tmp; 00306 } 00307 (*i)->set(conv); 00308 } 00309 } 00310 } 00311 00312 00313 bool 00314 OptionsCont::isUsableFileList(const std::string& name) const { 00315 Option* o = getSecure(name); 00316 // check whether the option is set 00317 // return false i not 00318 if (!o->isSet()) { 00319 return false; 00320 } 00321 // check whether the list of files is valid 00322 bool ok = true; 00323 std::vector<std::string> files = getStringVector(name); 00324 if (files.size() == 0) { 00325 WRITE_ERROR("The file list for '" + name + "' is empty."); 00326 ok = false; 00327 } 00328 for (std::vector<std::string>::const_iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) { 00329 if (!FileHelpers::exists(*fileIt)) { 00330 if (*fileIt != "") { 00331 WRITE_ERROR("File '" + *fileIt + "' does not exist."); 00332 ok = false; 00333 } else { 00334 WRITE_WARNING("Empty file name given; ignoring."); 00335 } 00336 } 00337 } 00338 return ok; 00339 } 00340 00341 00342 bool 00343 OptionsCont::checkDependingSuboptions(const std::string& name, const std::string& prefix) const { 00344 Option* o = getSecure(name); 00345 if (o->isSet()) { 00346 return true; 00347 } 00348 bool ok = true; 00349 std::vector<std::string> seenSynonymes; 00350 for (KnownContType::const_iterator i = myValues.begin(); i != myValues.end(); i++) { 00351 if (std::find(seenSynonymes.begin(), seenSynonymes.end(), (*i).first) != seenSynonymes.end()) { 00352 continue; 00353 } 00354 if ((*i).second->isSet() && !(*i).second->isDefault() && (*i).first.find(prefix) == 0) { 00355 WRITE_ERROR("Option '" + (*i).first + "' needs option '" + name + "'."); 00356 std::vector<std::string> synonymes = getSynonymes((*i).first); 00357 std::copy(synonymes.begin(), synonymes.end(), std::back_inserter(seenSynonymes)); 00358 ok = false; 00359 } 00360 } 00361 return ok; 00362 } 00363 00364 00365 void 00366 OptionsCont::reportDoubleSetting(const std::string& arg) const { 00367 std::vector<std::string> synonymes = getSynonymes(arg); 00368 std::ostringstream s; 00369 s << "A value for the option '" + arg + "' was already set.\n Possible synonymes: "; 00370 for (std::vector<std::string>::iterator i = synonymes.begin(); i != synonymes.end();) { 00371 s << (*i); 00372 i++; 00373 if (i != synonymes.end()) { 00374 s << ", "; 00375 } 00376 } 00377 WRITE_ERROR(s.str()); 00378 } 00379 00380 00381 std::string 00382 OptionsCont::convertChar(char abbr) const { 00383 char buf[2]; 00384 buf[0] = abbr; 00385 buf[1] = 0; 00386 std::string s(buf); 00387 return s; 00388 } 00389 00390 00391 bool 00392 OptionsCont::isBool(const std::string& name) const { 00393 Option* o = getSecure(name); 00394 return o->isBool(); 00395 } 00396 00397 00398 void 00399 OptionsCont::resetWritable() { 00400 for (ItemAddressContType::iterator i = myAddresses.begin(); i != myAddresses.end(); i++) { 00401 (*i)->resetWritable(); 00402 } 00403 } 00404 00405 00406 bool 00407 OptionsCont::isWriteable(const std::string& name) { 00408 Option* o = getSecure(name); 00409 return o->isWriteable(); 00410 } 00411 00412 00413 void 00414 OptionsCont::clear() { 00415 ItemAddressContType::iterator i; 00416 for (i = myAddresses.begin(); i != myAddresses.end(); i++) { 00417 delete(*i); 00418 } 00419 myAddresses.clear(); 00420 myValues.clear(); 00421 mySubTopics.clear(); 00422 mySubTopicEntries.clear(); 00423 } 00424 00425 00426 void 00427 OptionsCont::addDescription(const std::string& name, 00428 const std::string& subtopic, 00429 const std::string& description) { 00430 Option* o = getSecure(name); 00431 assert(o != 0); 00432 assert(find(mySubTopics.begin(), mySubTopics.end(), subtopic) != mySubTopics.end()); 00433 o->setDescription(description); 00434 mySubTopicEntries[subtopic].push_back(name); 00435 } 00436 00437 00438 void 00439 OptionsCont::setApplicationName(const std::string& appName, 00440 const std::string& fullName) { 00441 myAppName = appName; 00442 myFullName = fullName; 00443 } 00444 00445 00446 void 00447 OptionsCont::setApplicationDescription(const std::string& appDesc) { 00448 myAppDescription = appDesc; 00449 } 00450 00451 00452 void 00453 OptionsCont::addCallExample(const std::string& example, const std::string& desc) { 00454 myCallExamples.push_back(std::make_pair(example, desc)); 00455 } 00456 00457 00458 void 00459 OptionsCont::setAdditionalHelpMessage(const std::string& add) { 00460 myAdditionalMessage = add; 00461 } 00462 00463 00464 void 00465 OptionsCont::addCopyrightNotice(const std::string& copyrightLine) { 00466 myCopyrightNotices.push_back(copyrightLine); 00467 } 00468 00469 00470 void 00471 OptionsCont::clearCopyrightNotices() { 00472 myCopyrightNotices.clear(); 00473 } 00474 00475 00476 void 00477 OptionsCont::addOptionSubTopic(const std::string& topic) { 00478 mySubTopics.push_back(topic); 00479 mySubTopicEntries[topic] = std::vector<std::string>(); 00480 } 00481 00482 00483 void 00484 OptionsCont::splitLines(std::ostream& os, std::string what, 00485 size_t offset, size_t nextOffset) { 00486 while (what.length() > 0) { 00487 if (what.length() > 79 - offset) { 00488 size_t splitPos = what.rfind(';', 79 - offset); 00489 if (splitPos == std::string::npos) { 00490 splitPos = what.rfind(' ', 79 - offset); 00491 } else { 00492 splitPos++; 00493 } 00494 if (splitPos != std::string::npos) { 00495 os << what.substr(0, splitPos) << std::endl; 00496 what = what.substr(splitPos); 00497 for (size_t r = 0; r < nextOffset + 1; ++r) { 00498 os << ' '; 00499 } 00500 } else { 00501 os << what; 00502 what = ""; 00503 } 00504 offset = nextOffset; 00505 } else { 00506 os << what; 00507 what = ""; 00508 } 00509 } 00510 os << std::endl; 00511 } 00512 00513 00514 bool 00515 OptionsCont::processMetaOptions(bool missingOptions) { 00516 if (missingOptions) { 00517 // no options are given 00518 std::cout << myFullName << std::endl; 00519 for (std::vector<std::string>::const_iterator it = 00520 myCopyrightNotices.begin(); it != myCopyrightNotices.end(); ++it) { 00521 std::cout << " " << *it << std::endl; 00522 } 00523 std::cout << " License GPLv3+: GNU GPL Version 3 or later <http://gnu.org/licenses/gpl.html>\n"; 00524 std::cout << " Use --help to get the list of options." << std::endl; 00525 return true; 00526 } 00527 00528 // check whether the help shall be printed 00529 if (getBool("help")) { 00530 std::cout << myFullName << std::endl; 00531 for (std::vector<std::string>::const_iterator it = 00532 myCopyrightNotices.begin(); it != myCopyrightNotices.end(); ++it) { 00533 std::cout << " " << *it << std::endl; 00534 } 00535 printHelp(std::cout); 00536 return true; 00537 } 00538 // check whether the help shall be printed 00539 if (getBool("version")) { 00540 std::cout << myFullName << std::endl; 00541 for (std::vector<std::string>::const_iterator it = 00542 myCopyrightNotices.begin(); it != myCopyrightNotices.end(); ++it) { 00543 std::cout << " " << *it << std::endl; 00544 } 00545 std::cout << "\n" << myFullName << " is part of SUMO.\n"; 00546 std::cout << "SUMO is free software: you can redistribute it and/or modify\n"; 00547 std::cout << "it under the terms of the GNU General Public License as published by\n"; 00548 std::cout << "the Free Software Foundation, either version 3 of the License, or\n"; 00549 std::cout << "(at your option) any later version.\n\n"; 00550 std::cout << "This program is distributed in the hope that it will be useful,\n"; 00551 std::cout << "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"; 00552 std::cout << "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"; 00553 std::cout << "GNU General Public License for more details.\n\n"; 00554 std::cout << "You should have received a copy of the GNU General Public License\n"; 00555 std::cout << "along with this program. If not, see http://www.gnu.org/licenses/gpl.html" << std::endl; 00556 return true; 00557 } 00558 // check whether the settings shall be printed 00559 if (exists("print-options") && getBool("print-options")) { 00560 std::cout << (*this); 00561 } 00562 // check whether something has to be done with options 00563 // whether the current options shall be saved 00564 if (isSet("save-configuration", false)) { // sumo-gui does not register these 00565 if (getString("save-configuration") == "-" || getString("save-configuration") == "stdout") { 00566 writeConfiguration(std::cout, true, false, getBool("save-commented")); 00567 return true; 00568 } 00569 std::ofstream out(getString("save-configuration").c_str()); 00570 if (!out.good()) { 00571 throw ProcessError("Could not save configuration to '" + getString("save-configuration") + "'"); 00572 } else { 00573 writeConfiguration(out, true, false, getBool("save-commented")); 00574 if (getBool("verbose")) { 00575 WRITE_MESSAGE("Written configuration to '" + getString("save-configuration") + "'"); 00576 } 00577 return true; 00578 } 00579 } 00580 // whether the template shall be saved 00581 if (isSet("save-template", false)) { // sumo-gui does not register these 00582 if (getString("save-template") == "-" || getString("save-template") == "stdout") { 00583 writeConfiguration(std::cout, false, true, getBool("save-commented")); 00584 return true; 00585 } 00586 std::ofstream out(getString("save-template").c_str()); 00587 if (!out.good()) { 00588 throw ProcessError("Could not save template to '" + getString("save-template") + "'"); 00589 } else { 00590 writeConfiguration(out, false, true, getBool("save-commented")); 00591 if (getBool("verbose")) { 00592 WRITE_MESSAGE("Written template to '" + getString("save-template") + "'"); 00593 } 00594 return true; 00595 } 00596 } 00597 if (isSet("save-schema", false)) { // sumo-gui does not register these 00598 if (getString("save-schema") == "-" || getString("save-schema") == "stdout") { 00599 writeSchema(std::cout, getBool("save-commented")); 00600 return true; 00601 } 00602 std::ofstream out(getString("save-schema").c_str()); 00603 if (!out.good()) { 00604 throw ProcessError("Could not save schema to '" + getString("save-schema") + "'"); 00605 } else { 00606 writeSchema(out, getBool("save-commented")); 00607 if (getBool("verbose")) { 00608 WRITE_MESSAGE("Written schema to '" + getString("save-schema") + "'"); 00609 } 00610 return true; 00611 } 00612 } 00613 return false; 00614 } 00615 00616 void 00617 OptionsCont::printHelp(std::ostream& os) { 00618 std::vector<std::string>::const_iterator i, j; 00619 // print application description 00620 splitLines(os, myAppDescription, 0, 0); 00621 os << std::endl; 00622 // print usage BNF 00623 os << "Usage: " << myAppName << " [OPTION]*" << std::endl; 00624 // print additional text if any 00625 if (myAdditionalMessage.length() > 0) { 00626 os << myAdditionalMessage << std::endl << ' ' << std::endl; 00627 } 00628 // print the options 00629 // check their sizes first 00630 // we want to know how large the largest not-too-large-entry will be 00631 size_t tooLarge = 40; 00632 size_t maxSize = 0; 00633 for (i = mySubTopics.begin(); i != mySubTopics.end(); ++i) { 00634 const std::vector<std::string> &entries = mySubTopicEntries[*i]; 00635 for (j = entries.begin(); j != entries.end(); ++j) { 00636 Option* o = getSecure(*j); 00637 // name, two leading spaces and "--" 00638 size_t csize = (*j).length() + 2 + 4; 00639 // abbreviation length ("-X, "->4chars) if any 00640 std::vector<std::string> synonymes = getSynonymes(*j); 00641 if (find_if(synonymes.begin(), synonymes.end(), abbreviation_finder()) != synonymes.end()) { 00642 csize += 4; 00643 } 00644 // the type name 00645 if (!o->isBool()) { 00646 csize += 1 + o->getTypeName().length(); 00647 } 00648 // divider 00649 csize += 2; 00650 if (csize < tooLarge && maxSize < csize) { 00651 maxSize = csize; 00652 } 00653 } 00654 } 00655 00656 for (i = mySubTopics.begin(); i != mySubTopics.end(); ++i) { 00657 os << *i << " Options:" << std::endl; 00658 const std::vector<std::string> &entries = mySubTopicEntries[*i]; 00659 for (j = entries.begin(); j != entries.end(); ++j) { 00660 // start length computation 00661 size_t csize = (*j).length() + 2; 00662 Option* o = getSecure(*j); 00663 os << " "; 00664 // write abbreviation if given 00665 std::vector<std::string> synonymes = getSynonymes(*j); 00666 std::vector<std::string>::iterator a = find_if(synonymes.begin(), synonymes.end(), abbreviation_finder()); 00667 if (a != synonymes.end()) { 00668 os << '-' << (*a) << ", "; 00669 csize += 4; 00670 } 00671 // write leading '-'/"--" 00672 os << "--"; 00673 csize += 2; 00674 // write the name 00675 os << *j; 00676 // write the type if not a bool option 00677 if (!o->isBool()) { 00678 os << ' ' << o->getTypeName(); 00679 csize += 1 + o->getTypeName().length(); 00680 } 00681 csize += 2; 00682 // write the description formatting it 00683 os << " "; 00684 for (size_t r = maxSize; r > csize; --r) { 00685 os << ' '; 00686 } 00687 size_t offset = csize > tooLarge ? csize : maxSize; 00688 splitLines(os, o->getDescription(), offset, maxSize); 00689 } 00690 os << std::endl; 00691 } 00692 os << std::endl; 00693 // print usage examples, calc size first 00694 if (myCallExamples.size() != 0) { 00695 os << "Examples:" << std::endl; 00696 for (std::vector<std::pair<std::string,std::string> >::const_iterator e = myCallExamples.begin(); e != myCallExamples.end(); ++e) { 00697 os << " " << myAppName << ' ' << e->first << std::endl; 00698 os << " " << e->second << std::endl; 00699 } 00700 } 00701 os << std::endl; 00702 os << "Report bugs at <http://sourceforge.net/apps/trac/sumo/>." << std::endl; 00703 os << "Get in contact via <sumo-user@lists.sourceforge.net>." << std::endl; 00704 } 00705 00706 00707 void 00708 OptionsCont::writeConfiguration(std::ostream& os, bool filled, 00709 bool complete, bool addComments) { 00710 os << "<?xml version=\"1.0\"" << SUMOSAXAttributes::ENCODING << "?>\n\n"; 00711 os << "<configuration xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/" << myAppName << "Configuration.xsd\">" << std::endl << std::endl; 00712 for (std::vector<std::string>::const_iterator i = mySubTopics.begin(); i != mySubTopics.end(); ++i) { 00713 std::string subtopic = *i; 00714 if (subtopic == "Configuration" && !complete) { 00715 continue; 00716 } 00717 std::replace(subtopic.begin(), subtopic.end(), ' ', '_'); 00718 std::transform(subtopic.begin(), subtopic.end(), subtopic.begin(), tolower); 00719 const std::vector<std::string> &entries = mySubTopicEntries[*i]; 00720 bool hadOne = false; 00721 for (std::vector<std::string>::const_iterator j = entries.begin(); j != entries.end(); ++j) { 00722 Option* o = getSecure(*j); 00723 bool write = complete || (filled && !o->isDefault()); 00724 if (!write) { 00725 continue; 00726 } 00727 if (!hadOne) { 00728 os << " <" << subtopic << ">" << std::endl; 00729 } 00730 // add the comment if wished 00731 if (addComments) { 00732 os << " <!-- " << o->getDescription() << " -->" << std::endl; 00733 } 00734 // write the option and the value (if given) 00735 os << " <" << *j << " value=\""; 00736 if (o->isSet() && (filled || o->isDefault())) { 00737 os << o->getValueString(); 00738 } 00739 if (complete) { 00740 std::vector<std::string> synonymes = getSynonymes(*j); 00741 if (!synonymes.empty()) { 00742 os << "\" synonymes=\""; 00743 for (std::vector<std::string>::const_iterator s = synonymes.begin(); s != synonymes.end(); ++s) { 00744 if (s != synonymes.begin()) { 00745 os << " "; 00746 } 00747 os << (*s); 00748 } 00749 } 00750 os << "\" type=\"" << o->getTypeName(); 00751 if (!addComments) { 00752 os << "\" help=\"" << o->getDescription(); 00753 } 00754 } 00755 os << "\"/>" << std::endl; 00756 // append an endline if a comment was printed 00757 if (addComments) { 00758 os << std::endl; 00759 } 00760 hadOne = true; 00761 } 00762 if (hadOne) { 00763 os << " </" << subtopic << ">" << std::endl << std::endl; 00764 } 00765 } 00766 os << "</configuration>" << std::endl; 00767 } 00768 00769 00770 void 00771 OptionsCont::writeSchema(std::ostream& os, bool addComments) { 00772 os << "<?xml version=\"1.0\"" << SUMOSAXAttributes::ENCODING << "?>\n\n"; 00773 os << "<xsd:schema elementFormDefault=\"qualified\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">\n\n"; 00774 os << " <xsd:element name=\"configuration\" type=\"configurationType\"/>\n\n"; 00775 os << " <xsd:complexType name=\"configurationType\">\n"; 00776 os << " <xsd:sequence>\n"; 00777 for (std::vector<std::string>::const_iterator i = mySubTopics.begin(); i != mySubTopics.end(); ++i) { 00778 std::string subtopic = *i; 00779 if (subtopic == "Configuration") { 00780 continue; 00781 } 00782 std::replace(subtopic.begin(), subtopic.end(), ' ', '_'); 00783 std::transform(subtopic.begin(), subtopic.end(), subtopic.begin(), tolower); 00784 os << " <xsd:element name=\"" << subtopic << "\" type=\"" << subtopic << "Type\" minOccurs=\"0\" maxOccurs=\"1\"/>\n"; 00785 } 00786 os << " </xsd:sequence>\n"; 00787 os << " </xsd:complexType>\n\n"; 00788 for (std::vector<std::string>::const_iterator i = mySubTopics.begin(); i != mySubTopics.end(); ++i) { 00789 std::string subtopic = *i; 00790 if (subtopic == "Configuration") { 00791 continue; 00792 } 00793 std::replace(subtopic.begin(), subtopic.end(), ' ', '_'); 00794 std::transform(subtopic.begin(), subtopic.end(), subtopic.begin(), tolower); 00795 os << " <xsd:complexType name=\"" << subtopic << "Type\">\n"; 00796 os << " <xsd:sequence>\n"; 00797 const std::vector<std::string> &entries = mySubTopicEntries[*i]; 00798 for (std::vector<std::string>::const_iterator j = entries.begin(); j != entries.end(); ++j) { 00799 os << " <xsd:element name=\"" << *j << "\" type=\"" << *j << "Type\" minOccurs=\"0\" maxOccurs=\"1\"/>\n"; 00800 } 00801 os << " </xsd:sequence>\n"; 00802 os << " </xsd:complexType>\n\n"; 00803 for (std::vector<std::string>::const_iterator j = entries.begin(); j != entries.end(); ++j) { 00804 Option* o = getSecure(*j); 00805 std::string type = o->getTypeName(); 00806 std::transform(type.begin(), type.end(), type.begin(), tolower); 00807 if (type == "bool") { 00808 type = "boolean"; 00809 } else { 00810 if (type != "int" && type != "float") { 00811 type = "string"; 00812 } 00813 } 00814 os << " <xsd:complexType name=\"" << *j << "Type\">\n"; 00815 if (addComments) { 00816 os << " <!-- " << o->getDescription() << " -->\n"; 00817 } 00818 os << " <xsd:attribute name=\"value\" type=\"xsd:" << type << "\" use=\"required\"/>\n"; 00819 os << " <xsd:attribute name=\"synonymes\" type=\"xsd:string\" use=\"optional\"/>\n"; 00820 os << " <xsd:attribute name=\"type\" type=\"xsd:string\" use=\"optional\"/>\n"; 00821 os << " <xsd:attribute name=\"help\" type=\"xsd:string\" use=\"optional\"/>\n"; 00822 os << " </xsd:complexType>\n\n"; 00823 } 00824 } 00825 os << "</xsd:schema>\n"; 00826 } 00827 00828 00829 void 00830 OptionsCont::writeXMLHeader(std::ostream& os, const std::string xmlParams) { 00831 time_t rawtime; 00832 char buffer [80]; 00833 00834 os << "<?xml version=\"1.0\"" << xmlParams << "?>\n\n"; 00835 time(&rawtime); 00836 strftime(buffer, 80, "<!-- generated on %c by ", localtime(&rawtime)); 00837 os << buffer << myFullName << "\n"; 00838 writeConfiguration(os, true, false, false); 00839 os << "-->\n\n"; 00840 } 00841 00842 00843 std::vector<std::string> 00844 OptionsCont::getStringVector(const std::string& name) const { 00845 Option* o = getSecure(name); 00846 std::string def = o->getString(); 00847 if (def.find(';') != std::string::npos && !myHaveInformedAboutDeprecatedDivider) { 00848 WRITE_WARNING("Please note that using ';' as list separator is deprecated.\n From 1.0 onwards, only ',' will be accepted."); 00849 myHaveInformedAboutDeprecatedDivider = true; 00850 } 00851 StringTokenizer st(def, ";,", true); 00852 std::vector<std::string> ret = st.getVector(); 00853 for (std::vector<std::string>::iterator i = ret.begin(); i != ret.end(); ++i) { 00854 (*i) = StringUtils::prune(*i); 00855 } 00856 return ret; 00857 } 00858 00859 00860 bool 00861 OptionsCont::isInStringVector(const std::string& optionName, 00862 const std::string& itemName) { 00863 if (isSet(optionName)) { 00864 std::vector<std::string> values = getStringVector(optionName); 00865 return find(values.begin(), values.end(), itemName) != values.end(); 00866 } 00867 return false; 00868 } 00869 00870 00871 /****************************************************************************/