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/stdair_exceptions.hpp>
19 #include <stdair/basic/BasLogParams.hpp>
20 #include <stdair/basic/BasDBParams.hpp>
21 #include <stdair/service/Logger.hpp>
22 #include <stdair/bom/BookingRequestStruct.hpp>
23 #include <stdair/bom/BookingRequestTypes.hpp>
24 #include <stdair/basic/ProgressStatusSet.hpp>
25 #include <stdair/bom/EventStruct.hpp>
27 #include <stdair/ui/cmdline/SReadline.hpp>
30 #include <sevmgr/config/sevmgr-paths.hpp>
47 typedef std::vector<std::string> TokenList_T;
70 template<
class T> std::ostream& operator<< (std::ostream& os,
71 const std::vector<T>& v) {
72 std::copy (v.begin(), v.end(), std::ostream_iterator<T> (std::cout,
" "));
81 boost::program_options::options_description
generic (
"Generic options");
83 (
"prefix",
"print installation prefix")
84 (
"version,v",
"print version string")
85 (
"help,h",
"produce help message");
90 boost::program_options::options_description config (
"Configuration");
94 "Filename for the logs")
99 boost::program_options::options_description hidden (
"Hidden options");
102 boost::program_options::value< std::vector<std::string> >(),
103 "Show the copyright (license)");
105 boost::program_options::options_description cmdline_options;
106 cmdline_options.add(
generic).add(config).add(hidden);
108 boost::program_options::options_description config_file_options;
109 config_file_options.add(config).add(hidden);
110 boost::program_options::options_description visible (
"Allowed options");
111 visible.add(
generic).add(config);
113 boost::program_options::positional_options_description p;
114 p.add (
"copyright", -1);
116 boost::program_options::variables_map vm;
117 boost::program_options::
118 store (boost::program_options::command_line_parser (argc, argv).
119 options (cmdline_options).positional(p).run(), vm);
121 std::ifstream ifs (
"sevmgr.cfg");
122 boost::program_options::store (parse_config_file (ifs, config_file_options),
124 boost::program_options::notify (vm);
126 if (vm.count (
"help")) {
127 std::cout << visible << std::endl;
131 if (vm.count (
"version")) {
136 if (vm.count (
"prefix")) {
137 std::cout <<
"Installation prefix: " <<
PREFIXDIR << std::endl;
141 if (vm.count (
"log")) {
142 ioLogFilename = vm[
"log"].as< std::string >();
143 std::cout <<
"Log filename is: " << ioLogFilename << std::endl;
150 void initReadline (swift::SReadline& ioInputReader) {
153 std::vector<std::string> Completers;
158 Completers.push_back (
"help");
159 Completers.push_back (
"list");
160 Completers.push_back (
"list BookingRequest");
161 Completers.push_back (
"list BreakPoint");
162 Completers.push_back (
"select %date %time");
163 Completers.push_back (
"display");
164 Completers.push_back (
"next");
165 Completers.push_back (
"run");
166 Completers.push_back (
"json_list");
167 Completers.push_back (
"json_display");
168 Completers.push_back (
"quit");
173 ioInputReader.RegisterCompletions (Completers);
177 void parseEventDateTime (
const TokenList_T& iTokenList,
178 stdair::Date_T& ioEventDate,
179 stdair::Duration_T& ioEventTime) {
181 const std::string kMonthStr[12] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
182 "Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"};
184 unsigned short ioEventDateYear = ioEventDate.year();
185 unsigned short ioEventDateMonth = ioEventDate.month();
186 std::string ioEventDateMonthStr = kMonthStr[ioEventDateMonth-1];
187 unsigned short ioEventDateDay = ioEventDate.day();
189 unsigned short ioEventTimeHours = ioEventTime.hours();
190 unsigned short ioEventTimeMinutes = ioEventTime.minutes();
191 unsigned short ioEventTimeSeconds = ioEventTime.seconds();
194 if (iTokenList.empty() ==
false) {
197 TokenList_T::const_iterator itTok = iTokenList.begin();
200 if (itTok != iTokenList.end()) {
202 if (itTok->empty() ==
false) {
205 ioEventDateYear = boost::lexical_cast<
unsigned short> (*itTok);
206 if (ioEventDateYear < 100) {
207 ioEventDateYear += 2000;
210 }
catch (boost::bad_lexical_cast& eCast) {
211 std::cerr <<
"The year of the event date ('" << *itTok
212 <<
"') cannot be understood. The default value ("
213 << ioEventDateYear <<
") is kept. " << std::endl;
224 if (itTok != iTokenList.end()) {
226 if (itTok->empty() ==
false) {
229 const boost::regex lMonthRegex (
"^(\\d{1,2})$");
230 const bool isMonthANumber = regex_match (*itTok, lMonthRegex);
232 if (isMonthANumber ==
true) {
233 const unsigned short lMonth =
234 boost::lexical_cast<
unsigned short> (*itTok);
236 throw boost::bad_lexical_cast();
238 ioEventDateMonthStr = kMonthStr[lMonth-1];
241 const std::string lMonthStr (*itTok);
242 if (lMonthStr.size() < 3) {
243 throw boost::bad_lexical_cast();
245 std::string lMonthStr1 (lMonthStr.substr (0, 1));
246 boost::algorithm::to_upper (lMonthStr1);
247 std::string lMonthStr23 (lMonthStr.substr (1, 2));
248 boost::algorithm::to_lower (lMonthStr23);
249 ioEventDateMonthStr = lMonthStr1 + lMonthStr23;
252 }
catch (boost::bad_lexical_cast& eCast) {
253 std::cerr <<
"The month of the event date ('" << *itTok
254 <<
"') cannot be understood. The default value ("
255 << ioEventDateMonthStr <<
") is kept. " << std::endl;
263 if (itTok != iTokenList.end()) {
265 if (itTok->empty() ==
false) {
268 ioEventDateDay = boost::lexical_cast<
unsigned short> (*itTok);
270 }
catch (boost::bad_lexical_cast& eCast) {
271 std::cerr <<
"The day of the event date ('" << *itTok
272 <<
"') cannot be understood. The default value ("
273 << ioEventDateDay <<
") is kept. " << std::endl;
283 std::ostringstream lEventDateStr;
284 lEventDateStr << ioEventDateYear <<
"-" << ioEventDateMonthStr
285 <<
"-" << ioEventDateDay;
290 boost::gregorian::from_simple_string (lEventDateStr.str());
292 }
catch (boost::gregorian::bad_month& eCast) {
293 std::cerr <<
"The event date ('" << lEventDateStr.str()
294 <<
"') cannot be understood. The default value ("
295 << ioEventDate <<
") is kept. " << std::endl;
301 if (itTok != iTokenList.end()) {
303 if (itTok->empty() ==
false) {
306 ioEventTimeHours = boost::lexical_cast<
unsigned short> (*itTok);
308 }
catch (boost::bad_lexical_cast& eCast) {
309 std::cerr <<
"The hours of the event time ('" << *itTok
310 <<
"') cannot be understood. The default value ("
311 << ioEventTimeHours <<
") is kept. " << std::endl;
322 if (itTok != iTokenList.end()) {
324 if (itTok->empty() ==
false) {
327 ioEventTimeMinutes = boost::lexical_cast<
unsigned short> (*itTok);
329 }
catch (boost::bad_lexical_cast& eCast) {
330 std::cerr <<
"The minutes of the event time ('" << *itTok
331 <<
"') cannot be understood. The default value ("
332 << ioEventTimeMinutes <<
") is kept. " << std::endl;
343 if (itTok != iTokenList.end()) {
345 if (itTok->empty() ==
false) {
348 ioEventTimeSeconds = boost::lexical_cast<
unsigned short> (*itTok);
350 }
catch (boost::bad_lexical_cast& eCast) {
351 std::cerr <<
"The seconds of the event time ('" << *itTok
352 <<
"') cannot be understood. The default value ("
353 << ioEventTimeSeconds <<
") is kept. " << std::endl;
363 std::ostringstream lEventTimeStr;
364 lEventTimeStr << ioEventTimeHours <<
":" << ioEventTimeMinutes
365 <<
":" << ioEventTimeSeconds;
370 boost::posix_time::duration_from_string (lEventTimeStr.str());
372 }
catch (boost::gregorian::bad_month& eCast) {
373 std::cerr <<
"The event time ('" << lEventTimeStr.str()
374 <<
"') cannot be understood. The default value ("
375 << ioEventTime <<
") is kept. " << std::endl;
384 Command_T::Type_T extractCommand (TokenList_T& ioTokenList) {
385 Command_T::Type_T oCommandType = Command_T::LAST_VALUE;
388 if (ioTokenList.empty() ==
false) {
389 TokenList_T::iterator itTok = ioTokenList.begin();
390 std::string lCommand (*itTok);
391 boost::algorithm::to_lower (lCommand);
393 if (lCommand ==
"help") {
394 oCommandType = Command_T::HELP;
396 }
else if (lCommand ==
"list") {
397 oCommandType = Command_T::LIST;
399 }
else if (lCommand ==
"display") {
400 oCommandType = Command_T::DISPLAY;
402 }
else if (lCommand ==
"select") {
403 oCommandType = Command_T::SELECT;
405 }
else if (lCommand ==
"next") {
406 oCommandType = Command_T::NEXT;
408 }
else if (lCommand ==
"run") {
409 oCommandType = Command_T::RUN;
411 }
else if (lCommand ==
"json_list") {
412 oCommandType = Command_T::JSON_LIST;
414 }
else if (lCommand ==
"json_display") {
415 oCommandType = Command_T::JSON_DISPLAY;
417 }
else if (lCommand ==
"quit") {
418 oCommandType = Command_T::QUIT;
423 ioTokenList.erase (itTok);
426 oCommandType = Command_T::NOP;
433 std::string toString (
const TokenList_T& iTokenList) {
434 std::ostringstream oStr;
437 unsigned short idx = 0;
438 for (TokenList_T::const_iterator itTok = iTokenList.begin();
439 itTok != iTokenList.end(); ++itTok, ++idx) {
450 TokenList_T extractTokenList (
const TokenList_T& iTokenList,
451 const std::string& iRegularExpression) {
452 TokenList_T oTokenList;
456 const std::string lFullLine = toString (iTokenList);
459 boost::regex expression (iRegularExpression);
461 std::string::const_iterator start = lFullLine.begin();
462 std::string::const_iterator end = lFullLine.end();
464 boost::match_results<std::string::const_iterator> what;
465 boost::match_flag_type flags = boost::match_default | boost::format_sed;
466 regex_search (start, end, what, expression, flags);
470 const unsigned short lMatchSetSize = what.size();
471 for (
unsigned short matchIdx = 1; matchIdx != lMatchSetSize; ++matchIdx) {
472 const std::string lMatchedString (std::string (what[matchIdx].first,
473 what[matchIdx].second));
475 oTokenList.push_back (lMatchedString);
486 TokenList_T extractTokenListForDateTime (
const TokenList_T& iTokenList) {
499 const std::string lRegEx(
"^([[:digit:]]{2,4})?[/-]?[[:space:]]*"
500 "([[:alpha:]]{3}|[[:digit:]]{1,2})?[/-]?[[:space:]]*"
501 "([[:digit:]]{1,2})?[[:space:]]*"
502 "([[:digit:]]{1,2})?[:-]?[[:space:]]*"
503 "([[:alpha:]]{3}|[[:digit:]]{1,2})?[:-]?[[:space:]]*"
504 "([[:digit:]]{1,2})?[[:space:]]*$");
507 const TokenList_T& oTokenList = extractTokenList (iTokenList, lRegEx);
512 int main (
int argc,
char* argv[]) {
515 const unsigned int lHistorySize (100);
516 const std::string lHistoryFilename (
"sevmgr.hist");
517 const std::string lHistoryBackupFilename (
"sevmgr.hist.bak");
520 stdair::EventStruct lCurrentInteractiveEventStruct;
521 stdair::DateTime_T lCurrentInteractiveDateTime;
522 stdair::EventType::EN_EventType lCurrentInteractiveEventType;
525 stdair::Filename_T lLogFilename;
535 std::ofstream logOutputFile;
537 logOutputFile.open (lLogFilename.c_str());
538 logOutputFile.clear();
541 const stdair::BasLogParams lLogParams (stdair::LOG::DEBUG, logOutputFile);
545 sevmgrService.buildSampleQueue();
548 sevmgrService.popEvent(lCurrentInteractiveEventStruct);
551 STDAIR_LOG_DEBUG (
"====================================================");
552 STDAIR_LOG_DEBUG (
"= Beginning of the interactive session =");
553 STDAIR_LOG_DEBUG (
"====================================================");
556 swift::SReadline lReader (lHistoryFilename, lHistorySize);
557 initReadline (lReader);
560 std::string lUserInput;
561 bool EndOfInput (
false);
562 Command_T::Type_T lCommandType (Command_T::NOP);
564 while (lCommandType != Command_T::QUIT && EndOfInput ==
false) {
567 lCurrentInteractiveDateTime = lCurrentInteractiveEventStruct.getEventTime ();
568 lCurrentInteractiveEventType = lCurrentInteractiveEventStruct.getEventType ();
571 std::ostringstream oPromptStr;
572 oPromptStr <<
"sevmgr "
573 << stdair::EventType::getTypeLabelAsString(lCurrentInteractiveEventType)
574 <<
" / " << lCurrentInteractiveDateTime <<
"> " ;
576 TokenList_T lTokenListByReadline;
577 lUserInput = lReader.GetLine (oPromptStr.str(), lTokenListByReadline,
581 lReader.SaveHistory (lHistoryBackupFilename);
585 std::cout << std::endl;
590 lCommandType = extractCommand (lTokenListByReadline);
592 switch (lCommandType) {
595 case Command_T::HELP: {
596 std::cout << std::endl;
597 std::cout <<
"Commands: " << std::endl;
598 std::cout <<
" help" <<
"\t\t" <<
"Display this help" << std::endl;
599 std::cout <<
" quit" <<
"\t\t" <<
"Quit the application" << std::endl;
600 std::cout <<
" list" <<
"\t\t" <<
"List events in the queue. It is "
601 <<
"possible to filter events according to their types"
603 <<
"\t\t\t\t 'list_event BookingRequest' "
604 <<
"list all the booking requests" << std::endl
605 <<
"\t\t\t\t 'list_event BreakPoint' "
606 <<
"list all the break points" << std::endl;
607 std::cout <<
" select" <<
"\t\t"
608 <<
"Select an event into the 'list' to become the current one. For instance, try the command:\n"
609 <<
"\t\t 'select 2011-May-14 00:00:00'"
611 std::cout <<
" display" <<
"\t"
612 <<
"Display the current event" << std::endl;
613 std::cout <<
" next" <<
"\t\t"
614 <<
"Play the current event and pop the next one from the queue"
616 std::cout <<
" run" <<
"\t\t"
617 <<
"Play all the events until the next break-point, if any"
619 std::cout <<
" \nDebug Commands" << std::endl;
620 std::cout <<
" json_list" <<
"\t"
621 <<
"List events in the queue in a JSON format"
623 std::cout <<
" json_display" <<
"\t"
624 <<
"Display the current event in a JSON format"
626 std::cout << std::endl;
631 case Command_T::QUIT: {
636 case Command_T::LIST: {
639 std::ostringstream oEventListStr;
641 if (lTokenListByReadline.empty() ==
true) {
644 oEventListStr << sevmgrService.list ();
646 }
else if (lTokenListByReadline.size() == 1) {
648 assert (lTokenListByReadline.empty() ==
false);
649 const std::string lEventTypeStr (lTokenListByReadline[0]);
655 const stdair::EventType lEventType (lEventTypeStr);
656 const stdair::EventType::EN_EventType& lActualEventType =
657 lEventType.getType();
658 oEventListStr << sevmgrService.list (lActualEventType);
660 }
catch (stdair::CodeConversionException e) {
661 oEventListStr <<
"The event type '" << lEventTypeStr
662 <<
"' is not known. Try 'help' for "
663 <<
"more information on the 'list_event' command."
669 oEventListStr <<
"The event type is not understood: try 'help' for "
670 <<
"more information on the 'list_event' command."
673 std::cout << oEventListStr.str() << std::endl;
674 STDAIR_LOG_DEBUG (oEventListStr.str());
681 case Command_T::SELECT: {
684 TokenList_T lTokenList = extractTokenListForDateTime (lTokenListByReadline);
685 stdair::Date_T lUserDate = lCurrentInteractiveDateTime.date();
686 stdair::Duration_T lUserTime = lCurrentInteractiveDateTime.time_of_day();
687 parseEventDateTime (lTokenList, lUserDate, lUserTime);
689 std::cout <<
"Try to select event: "
690 << lUserDate <<
" " << lUserTime
693 const stdair::DateTime_T lUserDateTime =
694 boost::posix_time::ptime (lUserDate, lUserTime);
696 const bool hasSelectBeenSuccessful =
697 sevmgrService.select (lCurrentInteractiveEventStruct,
700 std::cout <<
"Selection successful: "
701 << hasSelectBeenSuccessful << std::endl;
708 case Command_T::DISPLAY: {
710 std::cout <<
"Display" << std::endl;
713 std::ostringstream oEventStr;
714 oEventStr << lCurrentInteractiveEventStruct.describe();
715 std::cout << oEventStr.str() << std::endl;
716 STDAIR_LOG_DEBUG (oEventStr.str());
723 case Command_T::NEXT: {
725 std::cout <<
"Next" << std::endl;
727 if (sevmgrService.isQueueDone() ==
true) {
730 std::ostringstream oEmptyQueueStr;
731 oEmptyQueueStr <<
"The event queue is empty: no event can be popped out.";
732 std::cout << oEmptyQueueStr.str() << std::endl;
733 STDAIR_LOG_DEBUG (oEmptyQueueStr.str());
741 stdair::ProgressStatusSet lPPS =
742 sevmgrService.popEvent (lCurrentInteractiveEventStruct);
745 std::ostringstream oEventStr;
746 oEventStr <<
"Poped event: '"
747 << lCurrentInteractiveEventStruct.describe() <<
"'.";
748 std::cout << oEventStr.str() << std::endl;
749 STDAIR_LOG_DEBUG (oEventStr.str());
756 case Command_T::RUN: {
758 std::cout <<
"Run" << std::endl;
761 sevmgrService.run (lCurrentInteractiveEventStruct);
762 lCurrentInteractiveEventType = lCurrentInteractiveEventStruct.getEventType ();
765 if (lCurrentInteractiveEventType == stdair::EventType::BRK_PT) {
766 std::ostringstream oBreakPointStr;
767 oBreakPointStr <<
"Break point found. Stop at: '"
768 << lCurrentInteractiveEventStruct.describe() <<
"'.";
769 std::cout << oBreakPointStr.str() << std::endl;
770 STDAIR_LOG_DEBUG (oBreakPointStr.str());
772 std::ostringstream oNoBreakPointStr;
773 oNoBreakPointStr <<
"No break point found. All the events have been played.\n"
774 <<
"The current event is the last one.";
775 std::cout << oNoBreakPointStr.str() << std::endl;
776 STDAIR_LOG_DEBUG (oNoBreakPointStr.str());
785 case Command_T::JSON_LIST: {
787 std::cout <<
"JSON List" << std::endl;
790 const std::string& lCSVEventQueueDumpAfter =
791 sevmgrService.jsonExportEventQueue ();
794 std::cout << lCSVEventQueueDumpAfter << std::endl;
795 STDAIR_LOG_DEBUG (lCSVEventQueueDumpAfter);
802 case Command_T::JSON_DISPLAY: {
804 std::cout <<
"JSON Display" << std::endl;
807 const std::string& lCSVEventDumpAfter =
808 sevmgrService.jsonExportEvent (lCurrentInteractiveEventStruct);
811 std::cout << lCSVEventDumpAfter << std::endl;
812 STDAIR_LOG_DEBUG (lCSVEventDumpAfter);
819 case Command_T::NOP: {
823 case Command_T::LAST_VALUE:
826 std::ostringstream oStr;
827 oStr <<
"That command is not yet understood: '" << lUserInput
828 <<
"' => " << lTokenListByReadline;
829 STDAIR_LOG_DEBUG (oStr.str());
830 std::cout << oStr.str() << std::endl;
836 STDAIR_LOG_DEBUG (
"End of the session. Exiting.");
837 std::cout <<
"End of the session. Exiting." << std::endl;
840 logOutputFile.close();