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