00001
00002
00003
00004
00005 #include <cassert>
00006 #include <vector>
00007 #include <fstream>
00008
00009 #include <stdair/basic/BasFileMgr.hpp>
00010 #include <stdair/bom/BomRoot.hpp>
00011 #include <stdair/service/Logger.hpp>
00012
00013 #include <stdair/basic/BasParserTypes.hpp>
00014
00015 #include <simfqt/command/FareParserHelper.hpp>
00016 #include <simfqt/command/FareRuleGenerator.hpp>
00017
00018
00019
00020 namespace SIMFQT {
00021
00022 namespace FareParserHelper {
00023
00024
00025
00026
00027
00028 ParserSemanticAction::
00029 ParserSemanticAction (FareRuleStruct& ioFareRule)
00030 : _fareRule (ioFareRule) {
00031 }
00032
00033
00034 storeFareId::
00035 storeFareId (FareRuleStruct& ioFareRule)
00036 : ParserSemanticAction (ioFareRule) {
00037 }
00038
00039
00040 void storeFareId::operator() (unsigned int iFareId,
00041 boost::spirit::qi::unused_type,
00042 boost::spirit::qi::unused_type) const {
00043 _fareRule.setFareID (iFareId);
00044
00045
00046
00047 const stdair::AirlineCode_T lEmptyAirlineCode ("");
00048 _fareRule.setAirlineCode(lEmptyAirlineCode);
00049 _fareRule.clearAirlineCodeList();
00050 const stdair::ClassCode_T lEmptyClassCode ("");
00051 _fareRule.setClassCode(lEmptyClassCode);
00052 _fareRule.clearClassCodeList();
00053 _fareRule._itSeconds = 0;
00054 }
00055
00056
00057 storeOrigin ::
00058 storeOrigin (FareRuleStruct& ioFareRule)
00059 : ParserSemanticAction (ioFareRule) {
00060 }
00061
00062
00063 void storeOrigin::operator() (std::vector<char> iChar,
00064 boost::spirit::qi::unused_type,
00065 boost::spirit::qi::unused_type) const {
00066 const stdair::AirportCode_T lOrigin (iChar.begin(), iChar.end());
00067 _fareRule.setOrigin (lOrigin);
00068
00069
00070 }
00071
00072
00073 storeDestination ::
00074 storeDestination (FareRuleStruct& ioFareRule)
00075 : ParserSemanticAction (ioFareRule) {
00076 }
00077
00078
00079 void storeDestination::operator() (std::vector<char> iChar,
00080 boost::spirit::qi::unused_type,
00081 boost::spirit::qi::unused_type) const {
00082 const stdair::AirportCode_T lDestination (iChar.begin(), iChar.end());
00083 _fareRule.setDestination (lDestination);
00084
00085
00086 }
00087
00088
00089 storeTripType ::
00090 storeTripType (FareRuleStruct& ioFareRule)
00091 : ParserSemanticAction (ioFareRule) {
00092 }
00093
00094
00095 void storeTripType::operator() (std::vector<char> iChar,
00096 boost::spirit::qi::unused_type,
00097 boost::spirit::qi::unused_type) const {
00098 const stdair::TripType_T lTripType (iChar.begin(), iChar.end());
00099 if (lTripType == "OW" || lTripType == "RT") {
00100 _fareRule.setTripType (lTripType);
00101 } else {
00102
00103 STDAIR_LOG_ERROR ("Invalid trip type " << lTripType);
00104 }
00105
00106
00107 }
00108
00109
00110
00111 storeDateRangeStart::
00112 storeDateRangeStart (FareRuleStruct& ioFareRule)
00113 : ParserSemanticAction (ioFareRule) {
00114 }
00115
00116
00117 void storeDateRangeStart::operator() (boost::spirit::qi::unused_type,
00118 boost::spirit::qi::unused_type,
00119 boost::spirit::qi::unused_type) const {
00120 const stdair::Date_T& lDateStart = _fareRule.calculateDate ();
00121 _fareRule.setDateRangeStart (lDateStart);
00122
00123
00124 }
00125
00126
00127 storeDateRangeEnd::
00128 storeDateRangeEnd(FareRuleStruct& ioFareRule)
00129 : ParserSemanticAction (ioFareRule) {
00130 }
00131
00132
00133 void storeDateRangeEnd::operator() (boost::spirit::qi::unused_type,
00134 boost::spirit::qi::unused_type,
00135 boost::spirit::qi::unused_type) const {
00136 const stdair::Date_T& lDateEnd = _fareRule.calculateDate ();
00137
00138
00139
00140 const stdair::DateOffset_T oneDay (1);
00141 const stdair::Date_T lBoostDateEnd = lDateEnd + oneDay;
00142 _fareRule.setDateRangeEnd (lBoostDateEnd);
00143
00144
00145 }
00146
00147
00148 storeStartRangeTime::
00149 storeStartRangeTime (FareRuleStruct& ioFareRule)
00150 : ParserSemanticAction (ioFareRule) {
00151 }
00152
00153
00154 void storeStartRangeTime::operator() (boost::spirit::qi::unused_type,
00155 boost::spirit::qi::unused_type,
00156 boost::spirit::qi::unused_type) const {
00157 const stdair::Duration_T& lTimeStart = _fareRule.calculateTime ();
00158 _fareRule.setTimeRangeStart (lTimeStart);
00159
00160
00161
00162 _fareRule._itSeconds = 0;
00163 }
00164
00165
00166 storeEndRangeTime::
00167 storeEndRangeTime (FareRuleStruct& ioFareRule)
00168 : ParserSemanticAction (ioFareRule) {
00169 }
00170
00171
00172 void storeEndRangeTime::operator() (boost::spirit::qi::unused_type,
00173 boost::spirit::qi::unused_type,
00174 boost::spirit::qi::unused_type) const {
00175 const stdair::Duration_T& lTimeEnd = _fareRule.calculateTime ();
00176 _fareRule.setTimeRangeEnd (lTimeEnd);
00177
00178
00179
00180 _fareRule._itSeconds = 0;
00181 }
00182
00183
00184 storePOS ::
00185 storePOS (FareRuleStruct& ioFareRule)
00186 : ParserSemanticAction (ioFareRule) {
00187 }
00188
00189
00190 void storePOS::operator() (std::vector<char> iChar,
00191 boost::spirit::qi::unused_type,
00192 boost::spirit::qi::unused_type) const {
00193 const stdair::CityCode_T lPOS (iChar.begin(), iChar.end());
00194 if (lPOS == _fareRule.getOrigin() || lPOS == _fareRule.getDestination()) {
00195 _fareRule.setPOS (lPOS);
00196 } else if (lPOS == "ROW") {
00197 const stdair::CityCode_T lPOSROW ("ROW");
00198 _fareRule.setPOS (lPOSROW);
00199 } else {
00200
00201 STDAIR_LOG_ERROR ("Invalid point of sale " << lPOS);
00202 }
00203
00204
00205 }
00206
00207
00208 storeCabinCode ::
00209 storeCabinCode (FareRuleStruct& ioFareRule)
00210 : ParserSemanticAction (ioFareRule) {
00211 }
00212
00213
00214 void storeCabinCode::operator() (char iChar,
00215 boost::spirit::qi::unused_type,
00216 boost::spirit::qi::unused_type) const {
00217 std::ostringstream ostr;
00218 ostr << iChar;
00219 const std::string cabinCodeStr = ostr.str();
00220 const stdair::CabinCode_T& lCabinCode (cabinCodeStr);
00221 _fareRule.setCabinCode (lCabinCode);
00222
00223
00224
00225
00226 }
00227
00228
00229 storeChannel ::
00230 storeChannel (FareRuleStruct& ioFareRule)
00231 : ParserSemanticAction (ioFareRule) {
00232 }
00233
00234
00235 void storeChannel::operator() (std::vector<char> iChar,
00236 boost::spirit::qi::unused_type,
00237 boost::spirit::qi::unused_type) const {
00238 const stdair::ChannelLabel_T lChannel (iChar.begin(), iChar.end());
00239 if (lChannel != "IN" && lChannel != "IF"
00240 && lChannel != "DN" && lChannel != "DF") {
00241
00242 STDAIR_LOG_ERROR ("Invalid channel " << lChannel);
00243 }
00244 _fareRule.setChannel (lChannel);
00245
00246
00247 }
00248
00249
00250 storeAdvancePurchase ::
00251 storeAdvancePurchase (FareRuleStruct& ioFareRule)
00252 : ParserSemanticAction (ioFareRule) {
00253 }
00254
00255
00256 void storeAdvancePurchase::operator() (unsigned int iAdancePurchase,
00257 boost::spirit::qi::unused_type,
00258 boost::spirit::qi::unused_type) const {
00259 const stdair::DayDuration_T& lAdancePurchase = iAdancePurchase;
00260 _fareRule.setAdvancePurchase (lAdancePurchase);
00261
00262
00263 }
00264
00265
00266 storeSaturdayStay ::
00267 storeSaturdayStay (FareRuleStruct& ioFareRule)
00268 : ParserSemanticAction (ioFareRule) {
00269 }
00270
00271
00272 void storeSaturdayStay::operator() (char iSaturdayStay,
00273 boost::spirit::qi::unused_type,
00274 boost::spirit::qi::unused_type) const {
00275 bool lBool = false;
00276 if (iSaturdayStay == 'T') {
00277 lBool = true;
00278 } else {
00279 if (iSaturdayStay != 'F') {
00280
00281 STDAIR_LOG_DEBUG ("Invalid saturdayStay char " << iSaturdayStay);
00282 }
00283 }
00284 const stdair::SaturdayStay_T lSaturdayStay (lBool);
00285 _fareRule.setSaturdayStay (lSaturdayStay);
00286
00287
00288 }
00289
00290
00291 storeChangeFees ::
00292 storeChangeFees (FareRuleStruct& ioFareRule)
00293 : ParserSemanticAction (ioFareRule) {
00294 }
00295
00296
00297 void storeChangeFees::operator() (char iChangefees,
00298 boost::spirit::qi::unused_type,
00299 boost::spirit::qi::unused_type) const {
00300
00301 bool lBool = false;
00302 if (iChangefees == 'T') {
00303 lBool = true;
00304 } else {
00305 if (iChangefees != 'F') {
00306
00307 STDAIR_LOG_DEBUG ("Invalid change fees char " << iChangefees);
00308 }
00309 }
00310 const stdair::ChangeFees_T lChangefees (lBool);
00311 _fareRule.setChangeFees (lChangefees);
00312
00313
00314 }
00315
00316
00317 storeNonRefundable ::
00318 storeNonRefundable (FareRuleStruct& ioFareRule)
00319 : ParserSemanticAction (ioFareRule) {
00320 }
00321
00322
00323 void storeNonRefundable::operator() (char iNonRefundable,
00324 boost::spirit::qi::unused_type,
00325 boost::spirit::qi::unused_type) const {
00326 bool lBool = false;
00327 if (iNonRefundable == 'T') {
00328 lBool = true;
00329 } else {
00330 if (iNonRefundable != 'F') {
00331
00332 STDAIR_LOG_DEBUG ("Invalid non refundable char " << iNonRefundable);
00333 }
00334 }
00335 const stdair::NonRefundable_T lNonRefundable (lBool);
00336 _fareRule.setNonRefundable (lNonRefundable);
00337
00338
00339 }
00340
00341
00342 storeMinimumStay ::
00343 storeMinimumStay (FareRuleStruct& ioFareRule)
00344 : ParserSemanticAction (ioFareRule) {
00345 }
00346
00347
00348 void storeMinimumStay::operator() (unsigned int iMinStay,
00349 boost::spirit::qi::unused_type,
00350 boost::spirit::qi::unused_type) const {
00351 const stdair::DayDuration_T lMinStay = iMinStay;
00352 _fareRule.setMinimumStay (lMinStay);
00353
00354
00355 }
00356
00357
00358 storeFare ::
00359 storeFare (FareRuleStruct& ioFareRule)
00360 : ParserSemanticAction (ioFareRule) {
00361 }
00362
00363
00364 void storeFare::operator() (double iFare,
00365 boost::spirit::qi::unused_type,
00366 boost::spirit::qi::unused_type) const {
00367 const stdair::PriceValue_T lFare = iFare;
00368 _fareRule.setFare (lFare);
00369
00370
00371 }
00372
00373
00374 storeAirlineCode ::
00375 storeAirlineCode (FareRuleStruct& ioFareRule)
00376 : ParserSemanticAction (ioFareRule) {
00377 }
00378
00379
00380 void storeAirlineCode::operator() (std::vector<char> iChar,
00381 boost::spirit::qi::unused_type,
00382 boost::spirit::qi::unused_type) const {
00383
00384 const stdair::AirlineCode_T lAirlineCode (iChar.begin(), iChar.end());
00385
00386 _fareRule.addAirlineCode (lAirlineCode);
00387
00388
00389 }
00390
00391
00392 storeClass ::
00393 storeClass (FareRuleStruct& ioFareRule)
00394 : ParserSemanticAction (ioFareRule) {
00395 }
00396
00397
00398 void storeClass::operator() (std::vector<char> iChar,
00399 boost::spirit::qi::unused_type,
00400 boost::spirit::qi::unused_type) const {
00401 std::ostringstream ostr;
00402 for (std::vector<char>::const_iterator lItVector = iChar.begin();
00403 lItVector != iChar.end();
00404 lItVector++) {
00405 ostr << *lItVector;
00406 }
00407 const std::string classCodeStr = ostr.str();
00408 const stdair::ClassCode_T lClassCode (classCodeStr);
00409
00410 _fareRule.addClassCode (lClassCode);
00411
00412
00413 }
00414
00415
00416 doEndFare::
00417 doEndFare (stdair::BomRoot& ioBomRoot,
00418 FareRuleStruct& ioFareRule)
00419 : ParserSemanticAction (ioFareRule),
00420 _bomRoot (ioBomRoot) {
00421 }
00422
00423
00424 void doEndFare::operator() (boost::spirit::qi::unused_type,
00425 boost::spirit::qi::unused_type,
00426 boost::spirit::qi::unused_type) const {
00427
00428
00429
00430 FareRuleGenerator::createAirportPair (_bomRoot, _fareRule);
00431 STDAIR_LOG_DEBUG(_fareRule.describe());
00432 }
00433
00434
00435
00436
00437
00438
00440 namespace bsq = boost::spirit::qi;
00441 namespace bsa = boost::spirit::ascii;
00442
00444 stdair::int1_p_t int1_p;
00445
00447 stdair::uint2_p_t uint2_p;
00448
00450 stdair::uint4_p_t uint4_p;
00451
00453 stdair::uint1_4_p_t uint1_4_p;
00454
00456 stdair::hour_p_t hour_p;
00457 stdair::minute_p_t minute_p;
00458 stdair::second_p_t second_p;
00459
00461 stdair::year_p_t year_p;
00462 stdair::month_p_t month_p;
00463 stdair::day_p_t day_p;
00464
00466
00467
00468
00470
00499 template <typename Iterator>
00500 struct FareRuleParser :
00501 public boost::spirit::qi::grammar<Iterator,
00502 boost::spirit::ascii::space_type> {
00503
00504 FareRuleParser (stdair::BomRoot& ioBomRoot,
00505 FareRuleStruct& iofareRule) :
00506
00507 FareRuleParser::base_type(start),
00508 _bomRoot(ioBomRoot), _fareRule(iofareRule) {
00509
00510
00511 start = *(comments | fare_rule);
00512
00513 comments = (bsq::lexeme[bsq::repeat(2)[bsa::char_('/')]
00514 >> +(bsa::char_ - bsq::eol)
00515 >> bsq::eol]
00516 | bsq::lexeme[bsa::char_('/') >>bsa::char_('*')
00517 >> +(bsa::char_ - bsa::char_('*'))
00518 >> bsa::char_('*') >> bsa::char_('/')]);
00519
00520 fare_rule = fare_key
00521 >> +( ';' >> segment )
00522 >> fare_rule_end[doEndFare(_bomRoot, _fareRule)];
00523
00524 fare_rule_end = bsa::char_(';');
00525
00526 fare_key = fare_id
00527 >> ';' >> origin >> ';' >> destination
00528 >> ';' >> tripType
00529 >> ';' >> dateRangeStart >> ';' >> dateRangeEnd
00530 >> ';' >> timeRangeStart >> ';' >> timeRangeEnd
00531 >> ';' >> point_of_sale >> ';' >> cabinCode >> ';' >> channel
00532 >> ';' >> advancePurchase >> ';' >> saturdayStay
00533 >> ';' >> changeFees >> ';' >> nonRefundable
00534 >> ';' >> minimumStay >> ';' >> fare;
00535
00536 fare_id = uint1_4_p[storeFareId(_fareRule)];
00537
00538 origin = bsq::repeat(3)[bsa::char_("A-Z")][storeOrigin(_fareRule)];
00539
00540 destination =
00541 bsq::repeat(3)[bsa::char_("A-Z")][storeDestination(_fareRule)];
00542
00543 tripType =
00544 bsq::repeat(2)[bsa::char_("A-Z")][storeTripType(_fareRule)];
00545
00546 dateRangeStart = date[storeDateRangeStart(_fareRule)];
00547
00548 dateRangeEnd = date[storeDateRangeEnd(_fareRule)];
00549
00550 date = bsq::lexeme
00551 [year_p[boost::phoenix::ref(_fareRule._itYear) = bsq::labels::_1]
00552 >> '-'
00553 >> month_p[boost::phoenix::ref(_fareRule._itMonth) = bsq::labels::_1]
00554 >> '-'
00555 >> day_p[boost::phoenix::ref(_fareRule._itDay) = bsq::labels::_1] ];
00556
00557 timeRangeStart = time[storeStartRangeTime(_fareRule)];
00558
00559 timeRangeEnd = time[storeEndRangeTime(_fareRule)];
00560
00561 time = bsq::lexeme
00562 [hour_p[boost::phoenix::ref(_fareRule._itHours) = bsq::labels::_1]
00563 >> ':'
00564 >> minute_p[boost::phoenix::ref(_fareRule._itMinutes) = bsq::labels::_1]
00565 >> - (':' >> second_p[boost::phoenix::ref(_fareRule._itSeconds) = bsq::labels::_1]) ];
00566
00567 point_of_sale = bsq::repeat(3)[bsa::char_("A-Z")][storePOS(_fareRule)];
00568
00569 cabinCode = bsa::char_("A-Z")[storeCabinCode(_fareRule)];
00570
00571 channel = bsq::repeat(2)[bsa::char_("A-Z")][storeChannel(_fareRule)];
00572
00573 advancePurchase = uint1_4_p[storeAdvancePurchase(_fareRule)];
00574
00575 saturdayStay = bsa::char_("A-Z")[storeSaturdayStay(_fareRule)];
00576
00577 changeFees = bsa::char_("A-Z")[storeChangeFees(_fareRule)];
00578
00579 nonRefundable = bsa::char_("A-Z")[storeNonRefundable(_fareRule)];
00580
00581 minimumStay = uint1_4_p[storeMinimumStay(_fareRule)];
00582
00583 fare = bsq::double_[storeFare(_fareRule)];
00584
00585 segment = bsq::repeat(2)[bsa::char_("A-Z")][storeAirlineCode(_fareRule)]
00586 >> ';'
00587 >> bsq::repeat(1,bsq::inf)[bsa::char_("A-Z")][storeClass(_fareRule)];
00588
00589
00590 BOOST_SPIRIT_DEBUG_NODE (start);
00591 BOOST_SPIRIT_DEBUG_NODE (comments);
00592 BOOST_SPIRIT_DEBUG_NODE (fare_rule);
00593 BOOST_SPIRIT_DEBUG_NODE (fare_rule_end);
00594 BOOST_SPIRIT_DEBUG_NODE (fare_key);
00595 BOOST_SPIRIT_DEBUG_NODE (fare_id);
00596 BOOST_SPIRIT_DEBUG_NODE (origin);
00597 BOOST_SPIRIT_DEBUG_NODE (destination);
00598 BOOST_SPIRIT_DEBUG_NODE (tripType);
00599 BOOST_SPIRIT_DEBUG_NODE (dateRangeStart);
00600 BOOST_SPIRIT_DEBUG_NODE (dateRangeEnd);
00601 BOOST_SPIRIT_DEBUG_NODE (date);
00602 BOOST_SPIRIT_DEBUG_NODE (timeRangeStart);
00603 BOOST_SPIRIT_DEBUG_NODE (time);
00604 BOOST_SPIRIT_DEBUG_NODE (point_of_sale);
00605 BOOST_SPIRIT_DEBUG_NODE (cabinCode);
00606 BOOST_SPIRIT_DEBUG_NODE (channel);
00607 BOOST_SPIRIT_DEBUG_NODE (advancePurchase);
00608 BOOST_SPIRIT_DEBUG_NODE (saturdayStay);
00609 BOOST_SPIRIT_DEBUG_NODE (changeFees);
00610 BOOST_SPIRIT_DEBUG_NODE (nonRefundable);
00611 BOOST_SPIRIT_DEBUG_NODE (minimumStay);
00612 BOOST_SPIRIT_DEBUG_NODE (fare);
00613 BOOST_SPIRIT_DEBUG_NODE (segment);
00614
00615 }
00616
00617
00618 boost::spirit::qi::rule<Iterator,
00619 boost::spirit::ascii::space_type>
00620 start, comments, fare_rule, fare_rule_end, fare_key, fare_id, origin,
00621 destination, tripType, dateRangeStart, dateRangeEnd, date,
00622 timeRangeStart, timeRangeEnd, time, point_of_sale, cabinCode, channel,
00623 advancePurchase, saturdayStay, changeFees, nonRefundable, minimumStay,
00624 fare, segment;
00625
00626
00627 stdair::BomRoot& _bomRoot;
00628 FareRuleStruct& _fareRule;
00629 };
00630
00631 }
00632
00633
00635
00636
00637
00639
00640
00641 FareRuleFileParser::
00642 FareRuleFileParser (stdair::BomRoot& ioBomRoot,
00643 const stdair::Filename_T& iFilename)
00644 : _filename (iFilename), _bomRoot (ioBomRoot) {
00645 init();
00646 }
00647
00648
00649 void FareRuleFileParser::init() {
00650
00651 const bool doesExistAndIsReadable =
00652 stdair::BasFileMgr::doesExistAndIsReadable (_filename);
00653
00654 if (doesExistAndIsReadable == false) {
00655 STDAIR_LOG_ERROR ("The fare schedule file " << _filename
00656 << " does not exist or can not be read.");
00657
00658 throw FareInputFileNotFoundException ("The fare file " + _filename
00659 + " does not exist or can not be read");
00660 }
00661 }
00662
00663
00664 void FareRuleFileParser::generateFareRules () {
00665
00666 STDAIR_LOG_DEBUG ("Parsing fare input file: " << _filename);
00667
00668
00669 const std::string* lFileName = &_filename;
00670 const char *lChar = (*lFileName).c_str();
00671 std::ifstream fileToBeParsed(lChar, std::ios_base::in);
00672
00673
00674 if (fileToBeParsed == false) {
00675 STDAIR_LOG_ERROR ("The fare file " << _filename << " can not be open."
00676 << std::endl);
00677
00678 throw FareInputFileNotFoundException ("The file " + _filename
00679 + " does not exist or can not be read");
00680 }
00681
00682
00683 stdair::base_iterator_t inputBegin (fileToBeParsed);
00684
00685
00686 stdair::iterator_t
00687 start (boost::spirit::make_default_multi_pass (inputBegin));
00688 stdair::iterator_t end;
00689
00690
00691 FareParserHelper::FareRuleParser<stdair::iterator_t> lFPParser(_bomRoot, _fareRule);
00692
00693
00694
00695 const bool hasParsingBeenSuccesful =
00696 boost::spirit::qi::phrase_parse (start, end, lFPParser,
00697 boost::spirit::ascii::space);
00698
00699 if (hasParsingBeenSuccesful == false) {
00700 STDAIR_LOG_ERROR ("Parsing of fare input file: " << _filename
00701 << " failed");
00702 throw FareFileParsingFailedException ("Parsing of fare input file: "
00703 + _filename + " failed");
00704 }
00705
00706 if (start != end) {
00707 STDAIR_LOG_ERROR ("Parsing of fare input file: " << _filename
00708 << " failed");
00709 throw FareFileParsingFailedException ("Parsing of fare input file: "
00710 + _filename + " failed");
00711 }
00712
00713 if (hasParsingBeenSuccesful == true && start == end) {
00714 STDAIR_LOG_DEBUG ("Parsing of fare input file: " << _filename
00715 << " succeeded");
00716 }
00717
00718 }
00719
00720 }