SEvMgr Logo  0.2.0
C++ Simulation-Oriented Discrete Event Management Library
sevmgr.cpp
Go to the documentation of this file.
00001 
00005 // STL
00006 #include <cassert>
00007 #include <iostream>
00008 #include <sstream>
00009 #include <fstream>
00010 #include <string>
00011 // Boost (Extended STL)
00012 #include <boost/program_options.hpp>
00013 #include <boost/tokenizer.hpp>
00014 #include <boost/regex.hpp>
00015 #include <boost/swap.hpp>
00016 #include <boost/algorithm/string/case_conv.hpp>
00017 // StdAir
00018 #include <stdair/basic/BasLogParams.hpp>
00019 #include <stdair/basic/BasDBParams.hpp>
00020 #include <stdair/service/Logger.hpp>
00021 // SEvMgr
00022 #include <sevmgr/SEVMGR_Service.hpp>
00023 #include <sevmgr/config/sevmgr-paths.hpp>
00024 // GNU Readline Wrapper
00025 #include <sevmgr/ui/cmdline/SReadline.hpp>
00026 
00027 // //////// Constants //////
00031 const std::string K_SEVMGR_DEFAULT_LOG_FILENAME ("sevmgr.log");
00032 
00036 const int K_SEVMGR_EARLY_RETURN_STATUS = 99;
00037 
00042 typedef std::vector<std::string> TokenList_T;
00043 
00047 struct Command_T {
00048   typedef enum {
00049     NOP = 0,
00050     QUIT,
00051     HELP,
00052     LIST,
00053     DISPLAY,
00054     SELECT,
00055     NEXT,
00056     RUN,
00057     JSON_LIST,
00058     JSON_DISPLAY,
00059     LAST_VALUE
00060   } Type_T;
00061 };
00062 
00063 // ///////// Parsing of Options & Configuration /////////
00064 // A helper function to simplify the main part.
00065 template<class T> std::ostream& operator<< (std::ostream& os,
00066                                             const std::vector<T>& v) {
00067   std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout, " ")); 
00068   return os;
00069 }
00070 
00074 int readConfiguration (int argc, char* argv[], std::string& ioLogFilename) {
00075   // Declare a group of options that will be allowed only on command line
00076   boost::program_options::options_description generic ("Generic options");
00077   generic.add_options()
00078     ("prefix", "print installation prefix")
00079     ("version,v", "print version string")
00080     ("help,h", "produce help message");
00081     
00082   // Declare a group of options that will be allowed both on command
00083   // line and in config file
00084 
00085   boost::program_options::options_description config ("Configuration");
00086   config.add_options()
00087     ("log,l",
00088      boost::program_options::value< std::string >(&ioLogFilename)->default_value(K_SEVMGR_DEFAULT_LOG_FILENAME),
00089      "Filename for the logs")
00090     ;
00091 
00092   // Hidden options, will be allowed both on command line and
00093   // in config file, but will not be shown to the user.
00094   boost::program_options::options_description hidden ("Hidden options");
00095   hidden.add_options()
00096     ("copyright",
00097      boost::program_options::value< std::vector<std::string> >(),
00098      "Show the copyright (license)");
00099         
00100   boost::program_options::options_description cmdline_options;
00101   cmdline_options.add(generic).add(config).add(hidden);
00102 
00103   boost::program_options::options_description config_file_options;
00104   config_file_options.add(config).add(hidden);
00105   boost::program_options::options_description visible ("Allowed options");
00106   visible.add(generic).add(config);
00107         
00108   boost::program_options::positional_options_description p;
00109   p.add ("copyright", -1);
00110         
00111   boost::program_options::variables_map vm;
00112   boost::program_options::
00113     store (boost::program_options::command_line_parser (argc, argv).
00114            options (cmdline_options).positional(p).run(), vm);
00115 
00116   std::ifstream ifs ("sevmgr.cfg");
00117   boost::program_options::store (parse_config_file (ifs, config_file_options),
00118                                  vm);
00119   boost::program_options::notify (vm);
00120     
00121   if (vm.count ("help")) {
00122     std::cout << visible << std::endl;
00123     return K_SEVMGR_EARLY_RETURN_STATUS;
00124   }
00125 
00126   if (vm.count ("version")) {
00127     std::cout << PACKAGE_NAME << ", version " << PACKAGE_VERSION << std::endl;
00128     return K_SEVMGR_EARLY_RETURN_STATUS;
00129   }
00130 
00131   if (vm.count ("prefix")) {
00132     std::cout << "Installation prefix: " << PREFIXDIR << std::endl;
00133     return K_SEVMGR_EARLY_RETURN_STATUS;
00134   }
00135 
00136   if (vm.count ("log")) {
00137     ioLogFilename = vm["log"].as< std::string >();
00138     std::cout << "Log filename is: " << ioLogFilename << std::endl;
00139   }
00140 
00141   return 0;
00142 }
00143 
00144 // //////////////////////////////////////////////////////////////////
00145 void initReadline (swift::SReadline& ioInputReader) {
00146 
00147   // Prepare the list of my own completers
00148   std::vector<std::string> Completers;
00149 
00150   // The following is supported:
00151   // - "identifiers"
00152   // - special identifier %file - means to perform a file name completion
00153   Completers.push_back ("help");
00154   Completers.push_back ("list %airline_code %flight_number");
00155   Completers.push_back ("select %airline_code %flight_number %flight_date");
00156   Completers.push_back ("display");
00157   Completers.push_back ("next");
00158   Completers.push_back ("run");
00159   Completers.push_back ("quit");
00160 
00161 
00162   // Now register the completers.
00163   // Actually it is possible to re-register another set at any time
00164   ioInputReader.RegisterCompletions (Completers);
00165 }
00166 
00167 // //////////////////////////////////////////////////////////////////
00168 Command_T::Type_T extractCommand (TokenList_T& ioTokenList) {
00169   Command_T::Type_T oCommandType = Command_T::LAST_VALUE;
00170 
00171   // Interpret the user input
00172   if (ioTokenList.empty() == false) {
00173     TokenList_T::iterator itTok = ioTokenList.begin();
00174     std::string lCommand (*itTok);
00175     boost::algorithm::to_lower (lCommand);
00176     
00177     if (lCommand == "help") {
00178       oCommandType = Command_T::HELP;
00179 
00180     } else if (lCommand == "list") {
00181       oCommandType = Command_T::LIST;
00182 
00183     } else if (lCommand == "display") {
00184       oCommandType = Command_T::DISPLAY;
00185 
00186     } else if (lCommand == "select") {
00187       oCommandType = Command_T::SELECT;
00188 
00189     } else if (lCommand == "next") {
00190       oCommandType = Command_T::NEXT;
00191 
00192     } else if (lCommand == "run") {
00193       oCommandType = Command_T::RUN;
00194 
00195     } else if (lCommand == "json_list") {
00196       oCommandType = Command_T::JSON_LIST;
00197     
00198     } else if (lCommand == "json_display") {
00199       oCommandType = Command_T::JSON_DISPLAY;
00200 
00201     } else if (lCommand == "quit") {
00202       oCommandType = Command_T::QUIT;
00203     }
00204 
00205     // Remove the first token (the command), as the corresponding information
00206     // has been extracted in the form of the returned command type enumeration
00207     ioTokenList.erase (itTok);
00208 
00209   } else {
00210     oCommandType = Command_T::NOP;
00211   }
00212 
00213   return oCommandType;
00214 }
00215 
00216 // //////////////////////////////////////////////////////////////////
00217 void parseFlightKey (const TokenList_T& iTokenList,
00218                      stdair::AirlineCode_T& ioAirlineCode,
00219                      stdair::FlightNumber_T& ioFlightNumber) {
00220   // Interpret the user input
00221   if (iTokenList.empty() == false) {
00222 
00223     // Read the airline code
00224     TokenList_T::const_iterator itTok = iTokenList.begin();
00225     if (itTok->empty() == false) {
00226       ioAirlineCode = *itTok;
00227       boost::algorithm::to_upper (ioAirlineCode);
00228     }
00229 
00230     // Read the flight-number
00231     ++itTok;
00232     if (itTok != iTokenList.end()) {
00233 
00234       if (itTok->empty() == false) {
00235         try {
00236 
00237           ioFlightNumber = boost::lexical_cast<stdair::FlightNumber_T> (*itTok);
00238 
00239         } catch (boost::bad_lexical_cast& eCast) {
00240           std::cerr << "The flight number ('" << *itTok
00241                     << "') cannot be understood. "
00242                     << "The default value (all) is kept."
00243                     << std::endl;
00244           return;
00245         }
00246       }
00247 
00248     } else {
00249       return;
00250     }
00251   }
00252 }
00253 
00254 // //////////////////////////////////////////////////////////////////
00255 void parseFlightDateKey (const TokenList_T& iTokenList,
00256                          stdair::AirlineCode_T& ioAirlineCode,
00257                          stdair::FlightNumber_T& ioFlightNumber,
00258                          stdair::Date_T& ioDepartureDate) {
00259   //
00260   const std::string kMonthStr[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
00261                                      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
00262   //
00263   unsigned short ioDepartureDateYear = ioDepartureDate.year();
00264   unsigned short ioDepartureDateMonth = ioDepartureDate.month();
00265   std::string ioDepartureDateMonthStr = kMonthStr[ioDepartureDateMonth-1];
00266   unsigned short ioDepartureDateDay = ioDepartureDate.day();
00267 
00268   // Interpret the user input
00269   if (iTokenList.empty() == false) {
00270 
00271     // Read the airline code
00272     TokenList_T::const_iterator itTok = iTokenList.begin();
00273     if (itTok->empty() == false) {
00274       ioAirlineCode = *itTok;
00275       boost::algorithm::to_upper (ioAirlineCode);
00276     }
00277 
00278     // Read the flight-number
00279     ++itTok;
00280     if (itTok != iTokenList.end()) {
00281 
00282       if (itTok->empty() == false) {
00283         try {
00284 
00285           ioFlightNumber = boost::lexical_cast<stdair::FlightNumber_T> (*itTok);
00286 
00287         } catch (boost::bad_lexical_cast& eCast) {
00288           std::cerr << "The flight number ('" << *itTok
00289                     << "') cannot be understood. "
00290                     << "The default value (all) is kept."
00291                     << std::endl;
00292           return;
00293         }
00294       }
00295 
00296     } else {
00297       return;
00298     }
00299 
00300     // Read the year for the departure date
00301     ++itTok;
00302     if (itTok != iTokenList.end()) {
00303 
00304       if (itTok->empty() == false) {
00305         try {
00306 
00307           ioDepartureDateYear = boost::lexical_cast<unsigned short> (*itTok);
00308           if (ioDepartureDateYear < 100) {
00309             ioDepartureDateYear += 2000;
00310           }
00311 
00312         } catch (boost::bad_lexical_cast& eCast) {
00313           std::cerr << "The year of the flight departure date ('" << *itTok
00314                     << "') cannot be understood. The default value ("
00315                     << ioDepartureDateYear << ") is kept. " << std::endl;
00316           return;
00317         }
00318       }
00319 
00320     } else {
00321       return;
00322     }
00323 
00324     // Read the month for the departure date
00325     ++itTok;
00326     if (itTok != iTokenList.end()) {
00327 
00328       if (itTok->empty() == false) {
00329         try {
00330 
00331           const boost::regex lMonthRegex ("^(\\d{1,2})$");
00332           const bool isMonthANumber = regex_match (*itTok, lMonthRegex);
00333         
00334           if (isMonthANumber == true) {
00335             const unsigned short lMonth =
00336               boost::lexical_cast<unsigned short> (*itTok);
00337             if (lMonth > 12) {
00338               throw boost::bad_lexical_cast();
00339             }
00340             ioDepartureDateMonthStr = kMonthStr[lMonth-1];
00341 
00342           } else {
00343             const std::string lMonthStr (*itTok);
00344             if (lMonthStr.size() < 3) {
00345               throw boost::bad_lexical_cast();
00346             }
00347             std::string lMonthStr1 (lMonthStr.substr (0, 1));
00348             boost::algorithm::to_upper (lMonthStr1);
00349             std::string lMonthStr23 (lMonthStr.substr (1, 2));
00350             boost::algorithm::to_lower (lMonthStr23);
00351             ioDepartureDateMonthStr = lMonthStr1 + lMonthStr23;
00352           }
00353 
00354         } catch (boost::bad_lexical_cast& eCast) {
00355           std::cerr << "The month of the flight departure date ('" << *itTok
00356                     << "') cannot be understood. The default value ("
00357                     << ioDepartureDateMonthStr << ") is kept. " << std::endl;
00358           return;
00359         }
00360       }
00361 
00362     } else {
00363       return;
00364     }
00365 
00366     // Read the day for the departure date
00367     ++itTok;
00368     if (itTok != iTokenList.end()) {
00369 
00370       if (itTok->empty() == false) {
00371         try {
00372 
00373           ioDepartureDateDay = boost::lexical_cast<unsigned short> (*itTok);
00374 
00375         } catch (boost::bad_lexical_cast& eCast) {
00376           std::cerr << "The day of the flight departure date ('" << *itTok
00377                     << "') cannot be understood. The default value ("
00378                     << ioDepartureDateDay << ") is kept. " << std::endl;
00379           return;
00380         }
00381       }
00382 
00383     } else {
00384       return;
00385     }
00386 
00387     // Re-compose the departure date
00388     std::ostringstream lDepartureDateStr;
00389     lDepartureDateStr << ioDepartureDateYear << "-" << ioDepartureDateMonthStr
00390                       << "-" << ioDepartureDateDay;
00391 
00392     try {
00393 
00394       ioDepartureDate =
00395         boost::gregorian::from_simple_string (lDepartureDateStr.str());
00396 
00397     } catch (boost::gregorian::bad_month& eCast) {
00398       std::cerr << "The flight departure date ('" << lDepartureDateStr.str()
00399                 << "') cannot be understood. The default value ("
00400                 << ioDepartureDate << ") is kept. " << std::endl;
00401       return;
00402     }
00403     
00404   }
00405 }
00406 
00407 // //////////////////////////////////////////////////////////////////
00408 void parseBookingClassKey (const TokenList_T& iTokenList,
00409                            stdair::ClassCode_T& ioBookingClass,
00410                            stdair::PartySize_T& ioPartySize,
00411                            stdair::AirportCode_T& ioOrigin,
00412                            stdair::AirportCode_T& ioDestination) {
00413   // Interpret the user input
00414   if (iTokenList.empty() == false) {
00415 
00416     // Read the booking class
00417     TokenList_T::const_iterator itTok = iTokenList.begin();
00418     if (itTok->empty() == false) {
00419       ioBookingClass = *itTok;
00420       boost::algorithm::to_upper (ioBookingClass);
00421     }
00422       
00423     // Read the party size
00424     ++itTok;
00425     if (itTok != iTokenList.end()) {
00426 
00427       if (itTok->empty() == false) {
00428         try {
00429 
00430           ioPartySize = boost::lexical_cast<stdair::PartySize_T> (*itTok);
00431 
00432         } catch (boost::bad_lexical_cast& eCast) {
00433           std::cerr << "The party size ('" << *itTok
00434                     << "') cannot be understood. The default value ("
00435                     << ioPartySize << ") is kept." << std::endl;
00436           return;
00437         }
00438       }
00439 
00440     } else {
00441       return;
00442     }
00443 
00444     // Read the origin
00445     ++itTok;
00446     if (itTok != iTokenList.end()) {
00447 
00448       if (itTok->empty() == false) {
00449         ioOrigin = *itTok;
00450         boost::algorithm::to_upper (ioOrigin);
00451       }
00452 
00453     } else {
00454       return;
00455     }
00456 
00457     // Read the destination
00458     ++itTok;
00459     if (itTok != iTokenList.end()) {
00460 
00461       if (itTok->empty() == false) {
00462         ioDestination = *itTok;
00463         boost::algorithm::to_upper (ioDestination);
00464       }
00465 
00466     } else {
00467       return;
00468     }
00469   }
00470 }
00471 
00472 // /////////////////////////////////////////////////////////
00473 std::string toString (const TokenList_T& iTokenList) {
00474   std::ostringstream oStr;
00475 
00476   // Re-create the string with all the tokens, trimmed by read-line
00477   unsigned short idx = 0;
00478   for (TokenList_T::const_iterator itTok = iTokenList.begin();
00479        itTok != iTokenList.end(); ++itTok, ++idx) {
00480     if (idx != 0) {
00481       oStr << " ";
00482     }
00483     oStr << *itTok;
00484   }
00485 
00486   return oStr.str();
00487 }
00488 
00489 // /////////////////////////////////////////////////////////
00490 TokenList_T extractTokenList (const TokenList_T& iTokenList,
00491                               const std::string& iRegularExpression) {
00492   TokenList_T oTokenList;
00493 
00494   // Re-create the string with all the tokens (which had been trimmed
00495   // by read-line)
00496   const std::string lFullLine = toString (iTokenList);
00497 
00498   // See the caller for the regular expression
00499   boost::regex expression (iRegularExpression);
00500   
00501   std::string::const_iterator start = lFullLine.begin();
00502   std::string::const_iterator end = lFullLine.end();
00503 
00504   boost::match_results<std::string::const_iterator> what;
00505   boost::match_flag_type flags = boost::match_default | boost::format_sed; 
00506   regex_search (start, end, what, expression, flags);
00507   
00508   // Put the matched strings in the list of tokens to be returned back
00509   // to the caller
00510   const unsigned short lMatchSetSize = what.size();
00511   for (unsigned short matchIdx = 1; matchIdx != lMatchSetSize; ++matchIdx) {
00512     const std::string lMatchedString (std::string (what[matchIdx].first,
00513                                                    what[matchIdx].second));
00514     //if (lMatchedString.empty() == false) {
00515     oTokenList.push_back (lMatchedString);
00516     //}
00517   }
00518 
00519   // DEBUG
00520   // std::cout << "After (token list): " << oTokenList << std::endl;
00521 
00522   return oTokenList;
00523 }    
00524 
00525 // /////////////////////////////////////////////////////////
00526 TokenList_T extractTokenListForFlight (const TokenList_T& iTokenList) {
00533   const std::string lRegEx ("^([[:alpha:]]{2,3})?"
00534                             "[[:space:]]*([[:digit:]]{1,4})?$");
00535 
00536   //
00537   const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
00538   return oTokenList;
00539 }    
00540 
00541 // /////////////////////////////////////////////////////////
00542 TokenList_T extractTokenListForFlightDate (const TokenList_T& iTokenList) {
00553   const std::string lRegEx("^([[:alpha:]]{2,3})?"
00554                            "[[:space:]]*([[:digit:]]{1,4})?"
00555                            "[/ ]*"
00556                            "([[:digit:]]{2,4})?[/-]?[[:space:]]*"
00557                            "([[:alpha:]]{3}|[[:digit:]]{1,2})?[/-]?[[:space:]]*"
00558                            "([[:digit:]]{1,2})?$");
00559 
00560   //
00561   const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
00562   return oTokenList;
00563 }    
00564 
00565 // /////////////////////////////////////////////////////////
00566 TokenList_T extractTokenListForClass (const TokenList_T& iTokenList) {
00575   const std::string lRegEx ("^([[:alpha:]])?"
00576                             "[[:space:]]*([[:digit:]]{1,3})?"
00577                             "[[:space:]]*([[:alpha:]]{3})?"
00578                             "[[:space:]]*([[:alpha:]]{3})?$");
00579 
00580   //
00581   const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
00582   return oTokenList;
00583 }    
00584 
00585 
00586 // ///////// M A I N ////////////
00587 int main (int argc, char* argv[]) {
00588 
00589   // Readline history
00590   const unsigned int lHistorySize (100);
00591   const std::string lHistoryFilename ("sevmgr.hist");
00592   const std::string lHistoryBackupFilename ("sevmgr.hist.bak");
00593 
00594   // Default parameters for the interactive session
00595   stdair::AirlineCode_T lLastInteractiveAirlineCode;
00596   stdair::FlightNumber_T lLastInteractiveFlightNumber;
00597   stdair::Date_T lLastInteractiveDate;
00598   stdair::AirlineCode_T lInteractiveAirlineCode;
00599   stdair::FlightNumber_T lInteractiveFlightNumber;
00600   stdair::Date_T lInteractiveDate;
00601   stdair::AirportCode_T lInteractiveOrigin;
00602   stdair::AirportCode_T lInteractiveDestination;
00603   stdair::ClassCode_T lInteractiveBookingClass;
00604   
00605   // Parameters for the sale
00606   std::string lSegmentDateKey;
00607 
00608   // Output log File
00609   stdair::Filename_T lLogFilename;
00610 
00611   // Call the command-line option parser
00612   const int lOptionParserStatus = readConfiguration (argc, argv, lLogFilename);
00613 
00614   if (lOptionParserStatus == K_SEVMGR_EARLY_RETURN_STATUS) {
00615     return 0;
00616   }
00617 
00618   // Set the log parameters
00619   std::ofstream logOutputFile;
00620   // Open and clean the log outputfile
00621   logOutputFile.open (lLogFilename.c_str());
00622   logOutputFile.clear();
00623 
00624   // Initialise the inventory service
00625   const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
00626   SEVMGR::SEVMGR_Service sevmgrService (lLogParams);
00627 
00628   // DEBUG
00629   STDAIR_LOG_DEBUG ("Welcome to SEvMgr");
00630 
00631   // Build the sample BOM tree for RMOL
00632   sevmgrService.buildSampleBom();
00633 
00634   // Update the default parameters for the following interactive session
00635   lInteractiveAirlineCode = "BA";
00636   lInteractiveFlightNumber = 9;
00637   lInteractiveDate = stdair::Date_T (2011, 06, 10);
00638   lInteractiveBookingClass = "Q";
00639   lInteractiveOrigin = "LHR";
00640   lInteractiveDestination = "SYD";
00641 
00642   // Save the last state
00643   lLastInteractiveAirlineCode = lInteractiveAirlineCode;
00644   lLastInteractiveFlightNumber = lInteractiveFlightNumber;
00645   lLastInteractiveDate = lInteractiveDate;
00646 
00647   // DEBUG
00648   STDAIR_LOG_DEBUG ("====================================================");
00649   STDAIR_LOG_DEBUG ("=       Beginning of the interactive session       =");
00650   STDAIR_LOG_DEBUG ("====================================================");
00651   STDAIR_LOG_DEBUG ("Last saved state: " << lLastInteractiveAirlineCode
00652                     << lLastInteractiveFlightNumber << " / "
00653                     << lLastInteractiveDate);
00654 
00655   // Initialise the GNU readline wrapper
00656   swift::SReadline lReader (lHistoryFilename, lHistorySize);
00657   initReadline (lReader);
00658 
00659   // Now we can ask user for a line
00660   std::string lUserInput;
00661   bool EndOfInput (false);
00662   Command_T::Type_T lCommandType (Command_T::NOP);
00663   
00664   while (lCommandType != Command_T::QUIT && EndOfInput == false) {
00665     // Prompt
00666     std::ostringstream oPromptStr;
00667     oPromptStr << "sevmgr "
00668                << lInteractiveAirlineCode << lInteractiveFlightNumber
00669                << " / " << lInteractiveDate
00670                << "> ";
00671     // Call read-line, which will fill the list of tokens
00672     TokenList_T lTokenListByReadline;
00673     lUserInput = lReader.GetLine (oPromptStr.str(), lTokenListByReadline,
00674                                   EndOfInput);
00675 
00676     // The history can be saved to an arbitrary file at any time
00677     lReader.SaveHistory (lHistoryBackupFilename);
00678 
00679     // The end-of-input typically corresponds to a CTRL-D typed by the user
00680     if (EndOfInput) {
00681       std::cout << std::endl;
00682       break;
00683     }
00684 
00685     // Interpret the user input
00686     lCommandType = extractCommand (lTokenListByReadline);
00687 
00688     switch (lCommandType) {
00689 
00690       // ////////////////////////////// Help ////////////////////////
00691     case Command_T::HELP: {
00692       std::cout << std::endl;
00693       std::cout << "Commands: " << std::endl;
00694       std::cout << " help" << "\t\t" << "Display this help" << std::endl;
00695       std::cout << " quit" << "\t\t" << "Quit the application" << std::endl;
00696       std::cout << " list" << "\t\t" << "List events" << std::endl;
00697       std::cout << " select" << "\t\t"
00698                 << "Select an event to become the current one" << std::endl;
00699       std::cout << " display" << "\t"
00700                 << "Display the current event" << std::endl;
00701       std::cout << " next" << "\t\t"
00702                 << "Play the current event and pop the next one from the queue"
00703                 << std::endl;
00704       std::cout << " run" << "\t\t"
00705                 << "Play all the events until the next break-point, if any"
00706                 << std::endl;
00707       std::cout << " \nDebug Commands" << std::endl;
00708       std::cout << " json_list" << "\t"
00709                 << "List events in a JSON format"
00710                 << std::endl;
00711       std::cout << " json_display" << "\t"
00712                 << "Display the current event in a JSON format"
00713                 << std::endl;
00714       std::cout << std::endl;
00715       break;
00716     }
00717  
00718       // ////////////////////////////// Quit ////////////////////////
00719     case Command_T::QUIT: {
00720       break;
00721     }
00722 
00723       // ////////////////////////////// List /////////////////////////
00724     case Command_T::LIST: {
00725       //
00726       std::cout << "List" << std::endl;
00727 
00728       //
00729       break;
00730     }
00731 
00732       // ////////////////////////////// Select ////////////////////////
00733     case Command_T::SELECT: {
00734       //
00735       std::cout << "Select" << std::endl;
00736 
00737       //
00738       break;
00739     }
00740 
00741       // ////////////////////////////// Display ////////////////////////
00742     case Command_T::DISPLAY: {
00743       //
00744       std::cout << "Display" << std::endl;
00745 
00746       //
00747       break;
00748     }
00749 
00750       // ////////////////////////////// Next ////////////////////////
00751     case Command_T::NEXT: {
00752       //
00753       std::cout << "Next" << std::endl;
00754 
00755       //
00756       break;
00757     }     
00758 
00759       // ////////////////////////////// Run ////////////////////////
00760     case Command_T::RUN: {
00761       //
00762       std::cout << "Run" << std::endl;
00763 
00764       //
00765       break;
00766     }     
00767 
00768       // ////////////////////////////// JSon List ////////////////////////
00769 
00770     case Command_T::JSON_LIST: { 
00771       //
00772       std::cout << "JSON List" << std::endl;
00773 
00774       //
00775       break;
00776     } 
00777 
00778       // ////////////////////////////// JSon Display ////////////////////////
00779 
00780     case Command_T::JSON_DISPLAY: {      
00781       //
00782       std::cout << "JSON Display" << std::endl;
00783 
00784       //
00785       break;
00786     }
00787 
00788       // /////////////////////////// Default / No value ///////////////////////
00789     case Command_T::NOP: {
00790       break;
00791     }
00792  
00793     case Command_T::LAST_VALUE:
00794     default: {
00795       // DEBUG
00796       std::ostringstream oStr;
00797       oStr << "That command is not yet understood: '" << lUserInput
00798            << "' => " << lTokenListByReadline;
00799       STDAIR_LOG_DEBUG (oStr.str());
00800       std::cout << oStr.str() << std::endl;
00801     }
00802     }
00803   }
00804 
00805   // DEBUG
00806   STDAIR_LOG_DEBUG ("End of the session. Exiting.");
00807   std::cout << "End of the session. Exiting." << std::endl;
00808 
00809   // Close the Log outputFile
00810   logOutputFile.close();
00811 
00812   /*
00813     Note: as that program is not intended to be run on a server in
00814     production, it is better not to catch the exceptions. When it
00815     happens (that an exception is throwned), that way we get the
00816     call stack.
00817   */
00818 
00819   return 0;     
00820 }