00001
00002
00003
00004
00005 #include <cassert>
00006 #include <fstream>
00007 #include <vector>
00008
00009 #include <stdair/basic/BasFileMgr.hpp>
00010 #include <stdair/basic/BasConst_Request.hpp>
00011 #include <stdair/bom/BomRoot.hpp>
00012 #include <stdair/service/Logger.hpp>
00013
00014 #include <stdair/basic/BasParserTypes.hpp>
00015
00016 #include <airrac/command/YieldParserHelper.hpp>
00017 #include <airrac/command/YieldRuleGenerator.hpp>
00018
00019 namespace AIRRAC {
00020
00021 namespace YieldParserHelper {
00022
00023
00024
00025
00026
00027 ParserSemanticAction::
00028 ParserSemanticAction (YieldRuleStruct& ioYieldRule)
00029 : _yieldRule (ioYieldRule) {
00030 }
00031
00032
00033 storeYieldId::
00034 storeYieldId (YieldRuleStruct& ioYieldRule)
00035 : ParserSemanticAction (ioYieldRule) {
00036 }
00037
00038
00039 void storeYieldId::operator() (unsigned int iYieldId,
00040 boost::spirit::qi::unused_type,
00041 boost::spirit::qi::unused_type) const {
00042 _yieldRule.setYieldID (iYieldId);
00043
00044
00045
00046
00047 const stdair::AirlineCode_T lEmptyAirlineCode ("");
00048 _yieldRule.setAirlineCode(lEmptyAirlineCode);
00049 _yieldRule.clearAirlineCodeList();
00050 const stdair::ClassCode_T lEmptyClassCode ("");
00051 _yieldRule.setClassCode(lEmptyClassCode);
00052 _yieldRule.clearClassCodeList();
00053 _yieldRule._itSeconds = 0;
00054
00055 }
00056
00057
00058 storeOrigin ::
00059 storeOrigin (YieldRuleStruct& ioYieldRule)
00060 : ParserSemanticAction (ioYieldRule) {
00061 }
00062
00063
00064 void storeOrigin::operator() (std::vector<char> iChar,
00065 boost::spirit::qi::unused_type,
00066 boost::spirit::qi::unused_type) const {
00067 const stdair::AirportCode_T lOrigin (iChar.begin(), iChar.end());
00068 _yieldRule.setOrigin (lOrigin);
00069
00070
00071 }
00072
00073
00074 storeDestination ::
00075 storeDestination (YieldRuleStruct& ioYieldRule)
00076 : ParserSemanticAction (ioYieldRule) {
00077 }
00078
00079
00080 void storeDestination::operator() (std::vector<char> iChar,
00081 boost::spirit::qi::unused_type,
00082 boost::spirit::qi::unused_type) const {
00083 const stdair::AirportCode_T lDestination (iChar.begin(), iChar.end());
00084 _yieldRule.setDestination (lDestination);
00085
00086
00087 }
00088
00089
00090 storeTripType ::
00091 storeTripType (YieldRuleStruct& ioYieldRule)
00092 : ParserSemanticAction (ioYieldRule) {
00093 }
00094
00095
00096 void storeTripType::operator() (std::vector<char> iChar,
00097 boost::spirit::qi::unused_type,
00098 boost::spirit::qi::unused_type) const {
00099 const stdair::TripType_T lTripType (iChar.begin(), iChar.end());
00100 if (lTripType == "OW" || lTripType == "RT") {
00101 _yieldRule.setTripType (lTripType);
00102 } else {
00103
00104 STDAIR_LOG_ERROR ("Invalid trip type " << lTripType);
00105 }
00106
00107
00108 }
00109
00110
00111
00112 storeDateRangeStart::
00113 storeDateRangeStart (YieldRuleStruct& ioYieldRule)
00114 : ParserSemanticAction (ioYieldRule) {
00115 }
00116
00117
00118 void storeDateRangeStart::operator() (boost::spirit::qi::unused_type,
00119 boost::spirit::qi::unused_type,
00120 boost::spirit::qi::unused_type) const {
00121 const stdair::Date_T& lDateStart = _yieldRule.calculateDate ();
00122 _yieldRule.setDateRangeStart (lDateStart);
00123
00124
00125 }
00126
00127
00128 storeDateRangeEnd::
00129 storeDateRangeEnd(YieldRuleStruct& ioYieldRule)
00130 : ParserSemanticAction (ioYieldRule) {
00131 }
00132
00133
00134 void storeDateRangeEnd::operator() (boost::spirit::qi::unused_type,
00135 boost::spirit::qi::unused_type,
00136 boost::spirit::qi::unused_type) const {
00137 const stdair::Date_T& lDateEnd = _yieldRule.calculateDate ();
00138
00139
00140
00141 const stdair::DateOffset_T oneDay (1);
00142 const stdair::Date_T lBoostDateEnd = lDateEnd + oneDay;
00143 _yieldRule.setDateRangeEnd (lBoostDateEnd);
00144
00145
00146 }
00147
00148
00149 storeStartRangeTime::
00150 storeStartRangeTime (YieldRuleStruct& ioYieldRule)
00151 : ParserSemanticAction (ioYieldRule) {
00152 }
00153
00154
00155 void storeStartRangeTime::operator() (boost::spirit::qi::unused_type,
00156 boost::spirit::qi::unused_type,
00157 boost::spirit::qi::unused_type) const {
00158 const stdair::Duration_T& lTimeStart = _yieldRule.calculateTime ();
00159 _yieldRule.setTimeRangeStart (lTimeStart);
00160
00161
00162
00163 _yieldRule._itSeconds = 0;
00164 }
00165
00166
00167 storeEndRangeTime::
00168 storeEndRangeTime (YieldRuleStruct& ioYieldRule)
00169 : ParserSemanticAction (ioYieldRule) {
00170 }
00171
00172
00173 void storeEndRangeTime::operator() (boost::spirit::qi::unused_type,
00174 boost::spirit::qi::unused_type,
00175 boost::spirit::qi::unused_type) const {
00176 const stdair::Duration_T& lTimeEnd = _yieldRule.calculateTime ();
00177 _yieldRule.setTimeRangeEnd (lTimeEnd);
00178
00179
00180
00181 _yieldRule._itSeconds = 0;
00182 }
00183
00184
00185 storePOS ::
00186 storePOS (YieldRuleStruct& ioYieldRule)
00187 : ParserSemanticAction (ioYieldRule) {
00188 }
00189
00190
00191 void storePOS::operator() (std::vector<char> iChar,
00192 boost::spirit::qi::unused_type,
00193 boost::spirit::qi::unused_type) const {
00194 const stdair::CityCode_T lPOS (iChar.begin(), iChar.end());
00195 if (lPOS == _yieldRule.getOrigin() || lPOS == _yieldRule.getDestination() ) {
00196 _yieldRule.setPOS (lPOS);
00197 } else if (lPOS == "ROW") {
00198 const stdair::CityCode_T lPOSROW ("ROW");
00199 _yieldRule.setPOS (lPOSROW);
00200 } else if (lPOS == stdair::DEFAULT_POS) {
00201 _yieldRule.setPOS (stdair::DEFAULT_POS);
00202 } else {
00203
00204 STDAIR_LOG_ERROR ("Invalid point of sale " << lPOS);
00205 }
00206
00207
00208 }
00209
00210
00211 storeCabinCode ::
00212 storeCabinCode (YieldRuleStruct& ioYieldRule)
00213 : ParserSemanticAction (ioYieldRule) {
00214 }
00215
00216
00217 void storeCabinCode::operator() (char iChar,
00218 boost::spirit::qi::unused_type,
00219 boost::spirit::qi::unused_type) const {
00220 std::ostringstream ostr;
00221 ostr << iChar;
00222 const std::string& cabinCodeStr = ostr.str();
00223 const stdair::CabinCode_T lCabinCode (cabinCodeStr);
00224 _yieldRule.setCabinCode (lCabinCode);
00225
00226
00227
00228
00229 }
00230
00231
00232 storeChannel ::
00233 storeChannel (YieldRuleStruct& ioYieldRule)
00234 : ParserSemanticAction (ioYieldRule) {
00235 }
00236
00237
00238 void storeChannel::operator() (std::vector<char> iChar,
00239 boost::spirit::qi::unused_type,
00240 boost::spirit::qi::unused_type) const {
00241 const stdair::ChannelLabel_T lChannel (iChar.begin(), iChar.end());
00242 if (lChannel != "IN" && lChannel != "IF" && lChannel != "DN"
00243 && lChannel != "DF" && lChannel != stdair::DEFAULT_CHANNEL) {
00244
00245 STDAIR_LOG_ERROR ("Invalid channel " << lChannel);
00246 }
00247 _yieldRule.setChannel (lChannel);
00248
00249
00250 }
00251
00252
00253 storeYield::
00254 storeYield (YieldRuleStruct& ioYieldRule)
00255 : ParserSemanticAction (ioYieldRule) {
00256 }
00257
00258
00259 void storeYield::operator() (double iYield,
00260 boost::spirit::qi::unused_type,
00261 boost::spirit::qi::unused_type) const {
00262 const stdair::YieldValue_T lYield= iYield;
00263 _yieldRule.setYield (lYield);
00264
00265
00266 }
00267
00268
00269 storeAirlineCode ::
00270 storeAirlineCode (YieldRuleStruct& ioYieldRule)
00271 : ParserSemanticAction (ioYieldRule) {
00272 }
00273
00274
00275 void storeAirlineCode::operator() (std::vector<char> iChar,
00276 boost::spirit::qi::unused_type,
00277 boost::spirit::qi::unused_type) const {
00278
00279 const stdair::AirlineCode_T lAirlineCode (iChar.begin(), iChar.end());
00280
00281 _yieldRule.setAirlineCode (lAirlineCode);
00282
00283 _yieldRule.addAirlineCode (lAirlineCode);
00284
00285
00286 }
00287
00288
00289 storeClass ::
00290 storeClass (YieldRuleStruct& ioYieldRule)
00291 : ParserSemanticAction (ioYieldRule) {
00292 }
00293
00294
00295 void storeClass::operator() (std::vector<char> iChar,
00296 boost::spirit::qi::unused_type,
00297 boost::spirit::qi::unused_type) const {
00298 std::ostringstream ostr;
00299 for (std::vector<char>::const_iterator lItVector = iChar.begin();
00300 lItVector != iChar.end();
00301 lItVector++) {
00302 ostr << *lItVector;
00303 }
00304 const std::string& classCodeStr = ostr.str();
00305 const stdair::ClassCode_T lClassCode (classCodeStr);
00306
00307 _yieldRule.addClassCode (lClassCode);
00308
00309
00310 }
00311
00312
00313 doEndYield::
00314 doEndYield (stdair::BomRoot& ioBomRoot,
00315 YieldRuleStruct& ioYieldRule)
00316 : ParserSemanticAction (ioYieldRule),
00317 _bomRoot (ioBomRoot) {
00318 }
00319
00320
00321 void doEndYield::operator() (boost::spirit::qi::unused_type,
00322 boost::spirit::qi::unused_type,
00323 boost::spirit::qi::unused_type) const {
00324
00325
00326
00327 YieldRuleGenerator::createAirportPair (_bomRoot, _yieldRule);
00328 STDAIR_LOG_DEBUG (_yieldRule.describe());
00329 }
00330
00331
00332
00333
00334
00335
00337 namespace bsq = boost::spirit::qi;
00338 namespace bsa = boost::spirit::ascii;
00339
00341 stdair::int1_p_t int1_p;
00342
00344 stdair::uint2_p_t uint2_p;
00345
00347 stdair::uint4_p_t uint4_p;
00348
00350 stdair::uint1_4_p_t uint1_4_p;
00351
00353 stdair::hour_p_t hour_p;
00354 stdair::minute_p_t minute_p;
00355 stdair::second_p_t second_p;
00356
00358 stdair::year_p_t year_p;
00359 stdair::month_p_t month_p;
00360 stdair::day_p_t day_p;
00361
00363
00364
00365
00367
00387 struct YieldRuleParser :
00388 public boost::spirit::qi::grammar<stdair::iterator_t,
00389 boost::spirit::ascii::space_type> {
00390
00391 YieldRuleParser (stdair::BomRoot& ioBomRoot,
00392 YieldRuleStruct& ioYieldRule) :
00393 YieldRuleParser::base_type(start),
00394 _bomRoot(ioBomRoot), _yieldRule(ioYieldRule) {
00395
00396 start = *(comments | yield_rule);
00397
00398 comments = (bsq::lexeme[bsq::repeat(2)[bsa::char_('/')]
00399 >> +(bsa::char_ - bsq::eol)
00400 >> bsq::eol]
00401 | bsq::lexeme[bsa::char_('/') >>bsa::char_('*')
00402 >> +(bsa::char_ - bsa::char_('*'))
00403 >> bsa::char_('*') >> bsa::char_('/')]);
00404
00405 yield_rule = yield_id
00406 >> ';' >> origin >> ';' >> destination
00407 >> ';' >> tripType
00408 >> ';' >> dateRangeStart >> ';' >> dateRangeEnd
00409 >> ';' >> timeRangeStart >> ';' >> timeRangeEnd
00410 >> ';' >> point_of_sale >> ';' >> cabinCode
00411 >> ';' >> channel >> ';' >> yield
00412 >> +( ';' >> segment )
00413 >> yield_rule_end[doEndYield(_bomRoot, _yieldRule)];
00414 ;
00415
00416 yield_id = uint1_4_p[storeYieldId(_yieldRule)];
00417
00418 origin = bsq::repeat(3)[bsa::char_("A-Z")][storeOrigin(_yieldRule)];
00419
00420 destination =
00421 bsq::repeat(3)[bsa::char_("A-Z")][storeDestination(_yieldRule)];
00422
00423 tripType =
00424 bsq::repeat(2)[bsa::char_("A-Z")][storeTripType(_yieldRule)];
00425
00426 dateRangeStart = date[storeDateRangeStart(_yieldRule)];
00427
00428 dateRangeEnd = date[storeDateRangeEnd(_yieldRule)];
00429
00430 date = bsq::lexeme
00431 [year_p[boost::phoenix::ref(_yieldRule._itYear) = bsq::labels::_1]
00432 >> '-'
00433 >> month_p[boost::phoenix::ref(_yieldRule._itMonth) = bsq::labels::_1]
00434 >> '-'
00435 >> day_p[boost::phoenix::ref(_yieldRule._itDay) = bsq::labels::_1] ];
00436
00437 timeRangeStart = time[storeStartRangeTime(_yieldRule)];
00438
00439 timeRangeEnd = time[storeEndRangeTime(_yieldRule)];
00440
00441 time = bsq::lexeme
00442 [hour_p[boost::phoenix::ref(_yieldRule._itHours) = bsq::labels::_1]
00443 >> ':'
00444 >> minute_p[boost::phoenix::ref(_yieldRule._itMinutes) = bsq::labels::_1]
00445 >> - (':' >> second_p[boost::phoenix::ref(_yieldRule._itSeconds) = bsq::labels::_1]) ];
00446
00447 point_of_sale = bsq::repeat(3)[bsa::char_("A-Z")][storePOS(_yieldRule)];
00448
00449 cabinCode = bsa::char_("A-Z")[storeCabinCode(_yieldRule)];
00450
00451 channel = bsq::repeat(2)[bsa::char_("A-Z")][storeChannel(_yieldRule)];
00452
00453 yield = bsq::double_[storeYield(_yieldRule)];
00454
00455 segment = bsq::repeat(2)[bsa::char_("A-Z")][storeAirlineCode(_yieldRule)]
00456 >> ';'
00457 >> bsq::repeat(1,bsq::inf)[bsa::char_("A-Z")][storeClass(_yieldRule)];
00458
00459 yield_rule_end = bsa::char_(';');
00460
00461
00462 BOOST_SPIRIT_DEBUG_NODE (start);
00463 BOOST_SPIRIT_DEBUG_NODE (comments);
00464 BOOST_SPIRIT_DEBUG_NODE (yield_rule);
00465 BOOST_SPIRIT_DEBUG_NODE (yield_id);
00466 BOOST_SPIRIT_DEBUG_NODE (origin);
00467 BOOST_SPIRIT_DEBUG_NODE (destination);
00468 BOOST_SPIRIT_DEBUG_NODE (tripType);
00469 BOOST_SPIRIT_DEBUG_NODE (dateRangeStart);
00470 BOOST_SPIRIT_DEBUG_NODE (dateRangeEnd);
00471 BOOST_SPIRIT_DEBUG_NODE (date);
00472 BOOST_SPIRIT_DEBUG_NODE (timeRangeStart);
00473 BOOST_SPIRIT_DEBUG_NODE (timeRangeEnd);
00474 BOOST_SPIRIT_DEBUG_NODE (time);
00475 BOOST_SPIRIT_DEBUG_NODE (point_of_sale);
00476 BOOST_SPIRIT_DEBUG_NODE (cabinCode);
00477 BOOST_SPIRIT_DEBUG_NODE (channel);
00478 BOOST_SPIRIT_DEBUG_NODE (yield);
00479 BOOST_SPIRIT_DEBUG_NODE (segment);
00480 BOOST_SPIRIT_DEBUG_NODE (yield_rule_end);
00481
00482 }
00483
00484
00485 boost::spirit::qi::rule<stdair::iterator_t,
00486 boost::spirit::ascii::space_type>
00487 start, comments, yield_rule, yield_id, origin, destination, tripType,
00488 dateRangeStart, dateRangeEnd, date, timeRangeStart, timeRangeEnd,
00489 time, point_of_sale, cabinCode, channel, yield, segment,
00490 yield_rule_end;
00491
00492
00493 stdair::BomRoot& _bomRoot;
00494 YieldRuleStruct& _yieldRule;
00495 };
00496
00497 }
00498
00499
00501
00502
00503
00505
00506
00507 YieldFileParser::YieldFileParser (stdair::BomRoot& ioBomRoot,
00508 const std::string& iFilename)
00509 : _filename (iFilename), _bomRoot (ioBomRoot) {
00510 init();
00511 }
00512
00513
00514 void YieldFileParser::init() {
00515
00516
00517 const bool doesExistAndIsReadable =
00518 stdair::BasFileMgr::doesExistAndIsReadable (_filename);
00519
00520 if (doesExistAndIsReadable == false) {
00521 STDAIR_LOG_ERROR ("The yield schedule file " << _filename
00522 << " does not exist or can not be read.");
00523
00524 throw YieldInputFileNotFoundException ("The yield file " + _filename + " does not exist or can not be read");
00525 }
00526 }
00527
00528
00529 void YieldFileParser::generateYieldStore () {
00530
00531 STDAIR_LOG_DEBUG ("Parsing yield input file: " << _filename);
00532
00533
00534 std::ifstream fileToBeParsed (_filename.c_str(), std::ios_base::in);
00535
00536
00537 if (fileToBeParsed == false) {
00538 STDAIR_LOG_ERROR ("The yield store file " << _filename
00539 << " can not be open."
00540 << std::endl);
00541
00542 throw YieldInputFileNotFoundException ("The file " + _filename
00543 + " does not exist or can not be read");
00544 }
00545
00546
00547 stdair::base_iterator_t inputBegin (fileToBeParsed);
00548
00549
00550 stdair::iterator_t
00551 start (boost::spirit::make_default_multi_pass (inputBegin));
00552 stdair::iterator_t end;
00553
00554
00555 YieldParserHelper::YieldRuleParser lYParser(_bomRoot, _yieldRule);
00556
00557
00558
00559 const bool hasParsingBeenSuccesful =
00560 boost::spirit::qi::phrase_parse (start, end, lYParser,
00561 boost::spirit::ascii::space);
00562
00563 if (hasParsingBeenSuccesful == false) {
00564
00565 STDAIR_LOG_ERROR ("Parsing of yield input file: " << _filename
00566 << " failed");
00567 throw YieldFileParsingFailedException ("Parsing of yield input file: "
00568 + _filename + " failed");
00569 }
00570 if (start != end) {
00571
00572 STDAIR_LOG_ERROR ("Parsing of yield input file: " << _filename
00573 << " failed");
00574 throw YieldFileParsingFailedException ("Parsing of yield input file: "
00575 + _filename + " failed");
00576 }
00577 if (hasParsingBeenSuccesful == true && start == end) {
00578 STDAIR_LOG_DEBUG ("Parsing of yield input file: " << _filename
00579 << " succeeded");
00580 }
00581
00582 }
00583
00584 }