12 #include <boost/program_options.hpp>
13 #include <boost/tokenizer.hpp>
14 #include <boost/regex.hpp>
15 #include <boost/swap.hpp>
16 #include <boost/algorithm/string/case_conv.hpp>
18 #include <stdair/basic/BasLogParams.hpp>
19 #include <stdair/basic/BasDBParams.hpp>
20 #include <stdair/service/Logger.hpp>
42 typedef std::vector<std::string> TokenList_T;
65 template<
class T> std::ostream& operator<< (std::ostream& os,
66 const std::vector<T>& v) {
67 std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout,
" "));
76 boost::program_options::options_description
generic (
"Generic options");
78 (
"prefix",
"print installation prefix")
79 (
"version,v",
"print version string")
80 (
"help,h",
"produce help message");
85 boost::program_options::options_description config (
"Configuration");
89 "Filename for the logs")
94 boost::program_options::options_description hidden (
"Hidden options");
97 boost::program_options::value< std::vector<std::string> >(),
98 "Show the copyright (license)");
100 boost::program_options::options_description cmdline_options;
101 cmdline_options.add(
generic).add(config).add(hidden);
103 boost::program_options::options_description config_file_options;
104 config_file_options.add(config).add(hidden);
105 boost::program_options::options_description visible (
"Allowed options");
106 visible.add(
generic).add(config);
108 boost::program_options::positional_options_description p;
109 p.add (
"copyright", -1);
111 boost::program_options::variables_map vm;
112 boost::program_options::
113 store (boost::program_options::command_line_parser (argc, argv).
114 options (cmdline_options).positional(p).run(), vm);
116 std::ifstream ifs (
"sevmgr.cfg");
117 boost::program_options::store (parse_config_file (ifs, config_file_options),
119 boost::program_options::notify (vm);
121 if (vm.count (
"help")) {
122 std::cout << visible << std::endl;
126 if (vm.count (
"version")) {
131 if (vm.count (
"prefix")) {
132 std::cout <<
"Installation prefix: " <<
PREFIXDIR << std::endl;
136 if (vm.count (
"log")) {
137 ioLogFilename = vm[
"log"].as< std::string >();
138 std::cout <<
"Log filename is: " << ioLogFilename << std::endl;
148 std::vector<std::string> Completers;
153 Completers.push_back (
"help");
154 Completers.push_back (
"list %airline_code %flight_number");
155 Completers.push_back (
"select %airline_code %flight_number %flight_date");
156 Completers.push_back (
"display");
157 Completers.push_back (
"next");
158 Completers.push_back (
"run");
159 Completers.push_back (
"quit");
168 Command_T::Type_T extractCommand (TokenList_T& ioTokenList) {
169 Command_T::Type_T oCommandType = Command_T::LAST_VALUE;
172 if (ioTokenList.empty() ==
false) {
173 TokenList_T::iterator itTok = ioTokenList.begin();
174 std::string lCommand (*itTok);
175 boost::algorithm::to_lower (lCommand);
177 if (lCommand ==
"help") {
178 oCommandType = Command_T::HELP;
180 }
else if (lCommand ==
"list") {
181 oCommandType = Command_T::LIST;
183 }
else if (lCommand ==
"display") {
184 oCommandType = Command_T::DISPLAY;
186 }
else if (lCommand ==
"select") {
187 oCommandType = Command_T::SELECT;
189 }
else if (lCommand ==
"next") {
190 oCommandType = Command_T::NEXT;
192 }
else if (lCommand ==
"run") {
193 oCommandType = Command_T::RUN;
195 }
else if (lCommand ==
"json_list") {
196 oCommandType = Command_T::JSON_LIST;
198 }
else if (lCommand ==
"json_display") {
199 oCommandType = Command_T::JSON_DISPLAY;
201 }
else if (lCommand ==
"quit") {
202 oCommandType = Command_T::QUIT;
207 ioTokenList.erase (itTok);
210 oCommandType = Command_T::NOP;
217 void parseFlightKey (
const TokenList_T& iTokenList,
218 stdair::AirlineCode_T& ioAirlineCode,
219 stdair::FlightNumber_T& ioFlightNumber) {
221 if (iTokenList.empty() ==
false) {
224 TokenList_T::const_iterator itTok = iTokenList.begin();
225 if (itTok->empty() ==
false) {
226 ioAirlineCode = *itTok;
227 boost::algorithm::to_upper (ioAirlineCode);
232 if (itTok != iTokenList.end()) {
234 if (itTok->empty() ==
false) {
237 ioFlightNumber = boost::lexical_cast<stdair::FlightNumber_T> (*itTok);
239 }
catch (boost::bad_lexical_cast& eCast) {
240 std::cerr <<
"The flight number ('" << *itTok
241 <<
"') cannot be understood. "
242 <<
"The default value (all) is kept."
255 void parseFlightDateKey (
const TokenList_T& iTokenList,
256 stdair::AirlineCode_T& ioAirlineCode,
257 stdair::FlightNumber_T& ioFlightNumber,
258 stdair::Date_T& ioDepartureDate) {
260 const std::string kMonthStr[12] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
261 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"};
263 unsigned short ioDepartureDateYear = ioDepartureDate.year();
264 unsigned short ioDepartureDateMonth = ioDepartureDate.month();
265 std::string ioDepartureDateMonthStr = kMonthStr[ioDepartureDateMonth-1];
266 unsigned short ioDepartureDateDay = ioDepartureDate.day();
269 if (iTokenList.empty() ==
false) {
272 TokenList_T::const_iterator itTok = iTokenList.begin();
273 if (itTok->empty() ==
false) {
274 ioAirlineCode = *itTok;
275 boost::algorithm::to_upper (ioAirlineCode);
280 if (itTok != iTokenList.end()) {
282 if (itTok->empty() ==
false) {
285 ioFlightNumber = boost::lexical_cast<stdair::FlightNumber_T> (*itTok);
287 }
catch (boost::bad_lexical_cast& eCast) {
288 std::cerr <<
"The flight number ('" << *itTok
289 <<
"') cannot be understood. "
290 <<
"The default value (all) is kept."
302 if (itTok != iTokenList.end()) {
304 if (itTok->empty() ==
false) {
307 ioDepartureDateYear = boost::lexical_cast<
unsigned short> (*itTok);
308 if (ioDepartureDateYear < 100) {
309 ioDepartureDateYear += 2000;
312 }
catch (boost::bad_lexical_cast& eCast) {
313 std::cerr <<
"The year of the flight departure date ('" << *itTok
314 <<
"') cannot be understood. The default value ("
315 << ioDepartureDateYear <<
") is kept. " << std::endl;
326 if (itTok != iTokenList.end()) {
328 if (itTok->empty() ==
false) {
331 const boost::regex lMonthRegex (
"^(\\d{1,2})$");
332 const bool isMonthANumber = regex_match (*itTok, lMonthRegex);
334 if (isMonthANumber ==
true) {
335 const unsigned short lMonth =
336 boost::lexical_cast<
unsigned short> (*itTok);
338 throw boost::bad_lexical_cast();
340 ioDepartureDateMonthStr = kMonthStr[lMonth-1];
343 const std::string lMonthStr (*itTok);
344 if (lMonthStr.size() < 3) {
345 throw boost::bad_lexical_cast();
347 std::string lMonthStr1 (lMonthStr.substr (0, 1));
348 boost::algorithm::to_upper (lMonthStr1);
349 std::string lMonthStr23 (lMonthStr.substr (1, 2));
350 boost::algorithm::to_lower (lMonthStr23);
351 ioDepartureDateMonthStr = lMonthStr1 + lMonthStr23;
354 }
catch (boost::bad_lexical_cast& eCast) {
355 std::cerr <<
"The month of the flight departure date ('" << *itTok
356 <<
"') cannot be understood. The default value ("
357 << ioDepartureDateMonthStr <<
") is kept. " << std::endl;
368 if (itTok != iTokenList.end()) {
370 if (itTok->empty() ==
false) {
373 ioDepartureDateDay = boost::lexical_cast<
unsigned short> (*itTok);
375 }
catch (boost::bad_lexical_cast& eCast) {
376 std::cerr <<
"The day of the flight departure date ('" << *itTok
377 <<
"') cannot be understood. The default value ("
378 << ioDepartureDateDay <<
") is kept. " << std::endl;
388 std::ostringstream lDepartureDateStr;
389 lDepartureDateStr << ioDepartureDateYear <<
"-" << ioDepartureDateMonthStr
390 <<
"-" << ioDepartureDateDay;
395 boost::gregorian::from_simple_string (lDepartureDateStr.str());
397 }
catch (boost::gregorian::bad_month& eCast) {
398 std::cerr <<
"The flight departure date ('" << lDepartureDateStr.str()
399 <<
"') cannot be understood. The default value ("
400 << ioDepartureDate <<
") is kept. " << std::endl;
408 void parseBookingClassKey (
const TokenList_T& iTokenList,
409 stdair::ClassCode_T& ioBookingClass,
410 stdair::PartySize_T& ioPartySize,
411 stdair::AirportCode_T& ioOrigin,
412 stdair::AirportCode_T& ioDestination) {
414 if (iTokenList.empty() ==
false) {
417 TokenList_T::const_iterator itTok = iTokenList.begin();
418 if (itTok->empty() ==
false) {
419 ioBookingClass = *itTok;
420 boost::algorithm::to_upper (ioBookingClass);
425 if (itTok != iTokenList.end()) {
427 if (itTok->empty() ==
false) {
430 ioPartySize = boost::lexical_cast<stdair::PartySize_T> (*itTok);
432 }
catch (boost::bad_lexical_cast& eCast) {
433 std::cerr <<
"The party size ('" << *itTok
434 <<
"') cannot be understood. The default value ("
435 << ioPartySize <<
") is kept." << std::endl;
446 if (itTok != iTokenList.end()) {
448 if (itTok->empty() ==
false) {
450 boost::algorithm::to_upper (ioOrigin);
459 if (itTok != iTokenList.end()) {
461 if (itTok->empty() ==
false) {
462 ioDestination = *itTok;
463 boost::algorithm::to_upper (ioDestination);
473 std::string toString (
const TokenList_T& iTokenList) {
474 std::ostringstream oStr;
477 unsigned short idx = 0;
478 for (TokenList_T::const_iterator itTok = iTokenList.begin();
479 itTok != iTokenList.end(); ++itTok, ++idx) {
490 TokenList_T extractTokenList (
const TokenList_T& iTokenList,
491 const std::string& iRegularExpression) {
492 TokenList_T oTokenList;
496 const std::string lFullLine = toString (iTokenList);
499 boost::regex expression (iRegularExpression);
501 std::string::const_iterator start = lFullLine.begin();
502 std::string::const_iterator end = lFullLine.end();
504 boost::match_results<std::string::const_iterator> what;
505 boost::match_flag_type flags = boost::match_default | boost::format_sed;
506 regex_search (start, end, what, expression, flags);
510 const unsigned short lMatchSetSize = what.size();
511 for (
unsigned short matchIdx = 1; matchIdx != lMatchSetSize; ++matchIdx) {
512 const std::string lMatchedString (std::string (what[matchIdx].first,
513 what[matchIdx].second));
515 oTokenList.push_back (lMatchedString);
526 TokenList_T extractTokenListForFlight (
const TokenList_T& iTokenList) {
533 const std::string lRegEx (
"^([[:alpha:]]{2,3})?"
534 "[[:space:]]*([[:digit:]]{1,4})?$");
537 const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
542 TokenList_T extractTokenListForFlightDate (
const TokenList_T& iTokenList) {
553 const std::string lRegEx(
"^([[:alpha:]]{2,3})?"
554 "[[:space:]]*([[:digit:]]{1,4})?"
556 "([[:digit:]]{2,4})?[/-]?[[:space:]]*"
557 "([[:alpha:]]{3}|[[:digit:]]{1,2})?[/-]?[[:space:]]*"
558 "([[:digit:]]{1,2})?$");
561 const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
566 TokenList_T extractTokenListForClass (
const TokenList_T& iTokenList) {
575 const std::string lRegEx (
"^([[:alpha:]])?"
576 "[[:space:]]*([[:digit:]]{1,3})?"
577 "[[:space:]]*([[:alpha:]]{3})?"
578 "[[:space:]]*([[:alpha:]]{3})?$");
581 const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
587 int main (
int argc,
char* argv[]) {
590 const unsigned int lHistorySize (100);
591 const std::string lHistoryFilename (
"sevmgr.hist");
592 const std::string lHistoryBackupFilename (
"sevmgr.hist.bak");
595 stdair::AirlineCode_T lLastInteractiveAirlineCode;
596 stdair::FlightNumber_T lLastInteractiveFlightNumber;
597 stdair::Date_T lLastInteractiveDate;
598 stdair::AirlineCode_T lInteractiveAirlineCode;
599 stdair::FlightNumber_T lInteractiveFlightNumber;
600 stdair::Date_T lInteractiveDate;
601 stdair::AirportCode_T lInteractiveOrigin;
602 stdair::AirportCode_T lInteractiveDestination;
603 stdair::ClassCode_T lInteractiveBookingClass;
606 std::string lSegmentDateKey;
609 stdair::Filename_T lLogFilename;
619 std::ofstream logOutputFile;
621 logOutputFile.open (lLogFilename.c_str());
622 logOutputFile.clear();
625 const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
629 STDAIR_LOG_DEBUG (
"Welcome to SEvMgr");
632 sevmgrService.buildSampleBom();
635 lInteractiveAirlineCode =
"BA";
636 lInteractiveFlightNumber = 9;
637 lInteractiveDate = stdair::Date_T (2011, 06, 10);
638 lInteractiveBookingClass =
"Q";
639 lInteractiveOrigin =
"LHR";
640 lInteractiveDestination =
"SYD";
643 lLastInteractiveAirlineCode = lInteractiveAirlineCode;
644 lLastInteractiveFlightNumber = lInteractiveFlightNumber;
645 lLastInteractiveDate = lInteractiveDate;
648 STDAIR_LOG_DEBUG (
"====================================================");
649 STDAIR_LOG_DEBUG (
"= Beginning of the interactive session =");
650 STDAIR_LOG_DEBUG (
"====================================================");
651 STDAIR_LOG_DEBUG (
"Last saved state: " << lLastInteractiveAirlineCode
652 << lLastInteractiveFlightNumber <<
" / "
653 << lLastInteractiveDate);
657 initReadline (lReader);
660 std::string lUserInput;
661 bool EndOfInput (
false);
662 Command_T::Type_T lCommandType (Command_T::NOP);
664 while (lCommandType != Command_T::QUIT && EndOfInput ==
false) {
666 std::ostringstream oPromptStr;
667 oPromptStr <<
"sevmgr "
668 << lInteractiveAirlineCode << lInteractiveFlightNumber
669 <<
" / " << lInteractiveDate
672 TokenList_T lTokenListByReadline;
673 lUserInput = lReader.GetLine (oPromptStr.str(), lTokenListByReadline,
677 lReader.SaveHistory (lHistoryBackupFilename);
681 std::cout << std::endl;
686 lCommandType = extractCommand (lTokenListByReadline);
688 switch (lCommandType) {
691 case Command_T::HELP: {
692 std::cout << std::endl;
693 std::cout <<
"Commands: " << std::endl;
694 std::cout <<
" help" <<
"\t\t" <<
"Display this help" << std::endl;
695 std::cout <<
" quit" <<
"\t\t" <<
"Quit the application" << std::endl;
696 std::cout <<
" list" <<
"\t\t" <<
"List events" << std::endl;
697 std::cout <<
" select" <<
"\t\t"
698 <<
"Select an event to become the current one" << std::endl;
699 std::cout <<
" display" <<
"\t"
700 <<
"Display the current event" << std::endl;
701 std::cout <<
" next" <<
"\t\t"
702 <<
"Play the current event and pop the next one from the queue"
704 std::cout <<
" run" <<
"\t\t"
705 <<
"Play all the events until the next break-point, if any"
707 std::cout <<
" \nDebug Commands" << std::endl;
708 std::cout <<
" json_list" <<
"\t"
709 <<
"List events in a JSON format"
711 std::cout <<
" json_display" <<
"\t"
712 <<
"Display the current event in a JSON format"
714 std::cout << std::endl;
719 case Command_T::QUIT: {
724 case Command_T::LIST: {
726 std::cout <<
"List" << std::endl;
733 case Command_T::SELECT: {
735 std::cout <<
"Select" << std::endl;
742 case Command_T::DISPLAY: {
744 std::cout <<
"Display" << std::endl;
751 case Command_T::NEXT: {
753 std::cout <<
"Next" << std::endl;
760 case Command_T::RUN: {
762 std::cout <<
"Run" << std::endl;
770 case Command_T::JSON_LIST: {
772 std::cout <<
"JSON List" << std::endl;
780 case Command_T::JSON_DISPLAY: {
782 std::cout <<
"JSON Display" << std::endl;
789 case Command_T::NOP: {
793 case Command_T::LAST_VALUE:
796 std::ostringstream oStr;
797 oStr <<
"That command is not yet understood: '" << lUserInput
798 <<
"' => " << lTokenListByReadline;
799 STDAIR_LOG_DEBUG (oStr.str());
800 std::cout << oStr.str() << std::endl;
806 STDAIR_LOG_DEBUG (
"End of the session. Exiting.");
807 std::cout <<
"End of the session. Exiting." << std::endl;
810 logOutputFile.close();