SUMO - Simulation of Urban MObility
OptionsCont.cpp
Go to the documentation of this file.
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 /****************************************************************************/
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines