AirSched Logo  0.1.2
C++ Simulated Airline Schedule Manager Library
ScheduleParserHelper.cpp
Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 // StdAir
00007 #include <stdair/basic/BasFileMgr.hpp>
00008 #include <stdair/bom/BomRoot.hpp>
00009 #include <stdair/service/Logger.hpp>
00010 // AIRSCHED
00011 #include <airsched/command/ScheduleParserHelper.hpp>
00012 #include <airsched/command/InventoryGenerator.hpp>
00013 
00014 namespace AIRSCHED {
00015 
00016   namespace ScheduleParserHelper {
00017       
00018     // //////////////////////////////////////////////////////////////////
00019     //  Semantic actions
00020     // //////////////////////////////////////////////////////////////////
00021 
00022     ParserSemanticAction::
00023     ParserSemanticAction (FlightPeriodStruct& ioFlightPeriod)
00024       : _flightPeriod (ioFlightPeriod) {
00025     }      
00026 
00027     // //////////////////////////////////////////////////////////////////
00028     storeAirlineCode::
00029     storeAirlineCode (FlightPeriodStruct& ioFlightPeriod)
00030       : ParserSemanticAction (ioFlightPeriod) {
00031     }
00032     
00033     // //////////////////////////////////////////////////////////////////
00034     void storeAirlineCode::operator() (iterator_t iStr,
00035                                        iterator_t iStrEnd) const { 
00036       const stdair::AirlineCode_T lAirlineCode (iStr, iStrEnd);
00037       _flightPeriod._airlineCode = lAirlineCode;
00038                 
00039       // As that's the beginning of a new flight, the list of legs
00040       // must be reset
00041       _flightPeriod._legList.clear();
00042     }
00043 
00044     // //////////////////////////////////////////////////////////////////
00045     storeFlightNumber::
00046     storeFlightNumber (FlightPeriodStruct& ioFlightPeriod)
00047       : ParserSemanticAction (ioFlightPeriod) {
00048     }
00049 
00050     // //////////////////////////////////////////////////////////////////
00051     void storeFlightNumber::operator() (unsigned int iNumber) const { 
00052       _flightPeriod._flightNumber = iNumber;
00053     }
00054 
00055     // //////////////////////////////////////////////////////////////////
00056     storeDateRangeStart::
00057     storeDateRangeStart (FlightPeriodStruct& ioFlightPeriod)
00058       : ParserSemanticAction (ioFlightPeriod) {
00059     }
00060     
00061     // //////////////////////////////////////////////////////////////////
00062     void storeDateRangeStart::operator() (iterator_t iStr,
00063                                           iterator_t iStrEnd) const {
00064       _flightPeriod._dateRangeStart = _flightPeriod.getDate();
00065         
00066       // Reset the number of seconds
00067       _flightPeriod._itSeconds = 0;
00068     }
00069       
00070     // //////////////////////////////////////////////////////////////////
00071     storeDateRangeEnd::
00072     storeDateRangeEnd (FlightPeriodStruct& ioFlightPeriod)
00073       : ParserSemanticAction (ioFlightPeriod) {
00074     }
00075     
00076     // //////////////////////////////////////////////////////////////////
00077     void storeDateRangeEnd::operator() (iterator_t iStr,
00078                                         iterator_t iStrEnd) const {
00079       // As a Boost date period (DatePeriod_T) defines the last day of
00080       // the period to be end-date - one day, we have to add one day to that
00081       // end date before.
00082       const stdair::DateOffset_T oneDay (1);
00083       _flightPeriod._dateRangeEnd = _flightPeriod.getDate() + oneDay;
00084 
00085       // Transform the date pair (i.e., the date range) into a date period
00086       _flightPeriod._dateRange =
00087         stdair::DatePeriod_T (_flightPeriod._dateRangeStart,
00088                               _flightPeriod._dateRangeEnd);
00089         
00090       // Reset the number of seconds
00091       _flightPeriod._itSeconds = 0;
00092     }
00093 
00094     // //////////////////////////////////////////////////////////////////
00095     storeDow::storeDow (FlightPeriodStruct& ioFlightPeriod)
00096       : ParserSemanticAction (ioFlightPeriod) {
00097     }
00098 
00099     // //////////////////////////////////////////////////////////////////
00100     void storeDow::operator() (iterator_t iStr, iterator_t iStrEnd) const {
00101       stdair::DOW_String_T lDow (iStr, iStrEnd);
00102       _flightPeriod._dow = lDow;
00103     }
00104       
00105     // //////////////////////////////////////////////////////////////////
00106     storeLegBoardingPoint::
00107     storeLegBoardingPoint (FlightPeriodStruct& ioFlightPeriod)
00108       : ParserSemanticAction (ioFlightPeriod) {
00109     }
00110 
00111     // //////////////////////////////////////////////////////////////////
00112     void storeLegBoardingPoint::operator() (iterator_t iStr,
00113                                             iterator_t iStrEnd) const {
00114       stdair::AirportCode_T lBoardingPoint (iStr, iStrEnd);
00115 
00116       // If a leg has already been parsed, add it to the FlightPeriod
00117       if (_flightPeriod._legAlreadyDefined == true) {
00118         _flightPeriod._legList.push_back (_flightPeriod._itLeg);
00119       } else {
00120         _flightPeriod._legAlreadyDefined = true;
00121       }
00122         
00123       // Set the (new) boarding point
00124       _flightPeriod._itLeg._boardingPoint = lBoardingPoint;
00125       
00126       // As that's the beginning of a new leg, the list of cabins
00127       // must be reset
00128       _flightPeriod._itLeg._cabinList.clear();
00129 
00130       // Add the airport code if it is not already stored in the airport lists
00131       _flightPeriod.addAirport (lBoardingPoint);
00132     }
00133 
00134     // //////////////////////////////////////////////////////////////////
00135     storeLegOffPoint::
00136     storeLegOffPoint (FlightPeriodStruct& ioFlightPeriod)
00137       : ParserSemanticAction (ioFlightPeriod) {
00138     }
00139 
00140     // //////////////////////////////////////////////////////////////////
00141     void storeLegOffPoint::operator() (iterator_t iStr,
00142                                        iterator_t iStrEnd) const {
00143       stdair::AirportCode_T lOffPoint (iStr, iStrEnd);
00144       _flightPeriod._itLeg._offPoint = lOffPoint;
00145 
00146       // Add the airport code if it is not already stored in the airport lists
00147       _flightPeriod.addAirport (lOffPoint);
00148     }
00149 
00150     // //////////////////////////////////////////////////////////////////
00151     storeBoardingTime::
00152     storeBoardingTime (FlightPeriodStruct& ioFlightPeriod)
00153       : ParserSemanticAction (ioFlightPeriod) {
00154     }
00155     
00156     // //////////////////////////////////////////////////////////////////
00157     void storeBoardingTime::operator() (iterator_t iStr,
00158                                         iterator_t iStrEnd) const {
00159       _flightPeriod._itLeg._boardingTime = _flightPeriod.getTime();
00160         
00161       // Reset the number of seconds
00162       _flightPeriod._itSeconds = 0;
00163 
00164       // Reset the date off-set
00165       _flightPeriod._dateOffset = 0;
00166     }
00167 
00168     // //////////////////////////////////////////////////////////////////
00169     storeOffTime::
00170     storeOffTime (FlightPeriodStruct& ioFlightPeriod)
00171       : ParserSemanticAction (ioFlightPeriod) {
00172     }
00173     
00174     // //////////////////////////////////////////////////////////////////
00175     void storeOffTime::operator() (iterator_t iStr,
00176                                    iterator_t iStrEnd) const {
00177       _flightPeriod._itLeg._offTime = _flightPeriod.getTime();
00178         
00179       // Reset the number of seconds
00180       _flightPeriod._itSeconds = 0;
00181 
00182       // As the boarding date off set is optional, it can be set only
00183       // afterwards, based on the staging date off-set value
00184       // (_flightPeriod._dateOffset).
00185       const stdair::DateOffset_T lDateOffset (_flightPeriod._dateOffset);
00186       _flightPeriod._itLeg._boardingDateOffset = lDateOffset;
00187     }
00188 
00189     // //////////////////////////////////////////////////////////////////
00190     storeElapsedTime::
00191     storeElapsedTime (FlightPeriodStruct& ioFlightPeriod)
00192       : ParserSemanticAction (ioFlightPeriod) {
00193     }
00194     
00195     // //////////////////////////////////////////////////////////////////
00196     void storeElapsedTime::operator() (iterator_t iStr,
00197                                        iterator_t iStrEnd) const {
00198       _flightPeriod._itLeg._elapsed = _flightPeriod.getTime();
00199         
00200       // Reset the number of seconds
00201       _flightPeriod._itSeconds = 0;
00202 
00203       // As the boarding date off set is optional, it can be set only
00204       // afterwards, based on the staging date off-set value
00205       // (_flightPeriod._dateOffset).
00206       const stdair::DateOffset_T lDateOffset (_flightPeriod._dateOffset);
00207       _flightPeriod._itLeg._offDateOffset = lDateOffset;
00208     }
00209 
00210     // //////////////////////////////////////////////////////////////////
00211     storeLegCabinCode::
00212     storeLegCabinCode (FlightPeriodStruct& ioFlightPeriod)
00213       : ParserSemanticAction (ioFlightPeriod) {
00214     }
00215     
00216     // //////////////////////////////////////////////////////////////////
00217     void storeLegCabinCode::operator() (char iChar) const { 
00218       _flightPeriod._itLegCabin._cabinCode = iChar; 
00219       //std::cout << "Cabin code: " << iChar << std::endl;
00220     }
00221 
00222     // //////////////////////////////////////////////////////////////////
00223     storeCapacity::
00224     storeCapacity (FlightPeriodStruct& ioFlightPeriod)
00225       : ParserSemanticAction (ioFlightPeriod) {
00226     }
00227     
00228     // //////////////////////////////////////////////////////////////////
00229     void storeCapacity::operator() (double iReal) const { 
00230       _flightPeriod._itLegCabin._capacity = iReal; 
00231       //std::cout << "Capacity: " << iReal << std::endl;
00232 
00233       // The capacity is the last (according to the arrival order
00234       // within the schedule input file) detail of the leg cabin. Hence,
00235       // when a capacity is parsed, it means that the full cabin
00236       // details have already been parsed as well: the cabin can
00237       // thus be added to the leg.
00238       _flightPeriod._itLeg._cabinList.push_back (_flightPeriod._itLegCabin);
00239     }
00240 
00241     // //////////////////////////////////////////////////////////////////
00242     storeSegmentSpecificity::
00243     storeSegmentSpecificity (FlightPeriodStruct& ioFlightPeriod)
00244       : ParserSemanticAction (ioFlightPeriod) {
00245     }
00246 
00247     // //////////////////////////////////////////////////////////////////
00248     void storeSegmentSpecificity::operator() (char iChar) const {
00249       if (iChar == '0') {
00250         _flightPeriod._areSegmentDefinitionsSpecific = false;
00251       } else {
00252         _flightPeriod._areSegmentDefinitionsSpecific = true;
00253       }
00254 
00255       // Do a few sanity checks: the two lists should get exactly the same
00256       // content (in terms of airport codes). The only difference is that one
00257       // is a STL set, and the other a STL vector.
00258       assert (_flightPeriod._airportList.size()
00259               == _flightPeriod._airportOrderedList.size());
00260       assert (_flightPeriod._airportList.size() >= 2);
00261         
00262       // Since all the legs have now been parsed, we get all the airports
00263       // and the segments may be built.
00264       _flightPeriod.buildSegments();
00265     }
00266       
00267     // //////////////////////////////////////////////////////////////////
00268     storeSegmentBoardingPoint::
00269     storeSegmentBoardingPoint (FlightPeriodStruct& ioFlightPeriod)
00270       : ParserSemanticAction (ioFlightPeriod) {
00271     }
00272 
00273     // //////////////////////////////////////////////////////////////////
00274     void storeSegmentBoardingPoint::operator() (iterator_t iStr,
00275                                              iterator_t iStrEnd) const {
00276       stdair::AirportCode_T lBoardingPoint (iStr, iStrEnd);
00277       _flightPeriod._itSegment._boardingPoint = lBoardingPoint;
00278     }
00279 
00280     // //////////////////////////////////////////////////////////////////
00281     storeSegmentOffPoint::
00282     storeSegmentOffPoint (FlightPeriodStruct& ioFlightPeriod)
00283       : ParserSemanticAction (ioFlightPeriod) {
00284     }
00285 
00286     // //////////////////////////////////////////////////////////////////
00287     void storeSegmentOffPoint::operator() (iterator_t iStr,
00288                                            iterator_t iStrEnd) const {
00289       stdair::AirportCode_T lOffPoint (iStr, iStrEnd);
00290       _flightPeriod._itSegment._offPoint = lOffPoint;
00291     }
00292 
00293     // //////////////////////////////////////////////////////////////////
00294     storeSegmentCabinCode::
00295     storeSegmentCabinCode (FlightPeriodStruct& ioFlightPeriod)
00296       : ParserSemanticAction (ioFlightPeriod) {
00297     }
00298     
00299     // //////////////////////////////////////////////////////////////////
00300     void storeSegmentCabinCode::operator() (char iChar) const { 
00301       _flightPeriod._itSegmentCabin._cabinCode = iChar; 
00302     }
00303 
00304     // //////////////////////////////////////////////////////////////////
00305     storeClasses::
00306     storeClasses (FlightPeriodStruct& ioFlightPeriod)
00307       : ParserSemanticAction (ioFlightPeriod) {
00308     }
00309 
00310     // //////////////////////////////////////////////////////////////////
00311     void storeClasses::operator() (iterator_t iStr,
00312                                    iterator_t iStrEnd) const {
00313       std::string lClasses (iStr, iStrEnd);
00314       _flightPeriod._itSegmentCabin._classes = lClasses;
00315 
00316       // The list of classes is the last (according to the arrival order
00317       // within the schedule input file) detail of the segment cabin. Hence,
00318       // when a list of classes is parsed, it means that the full segment
00319       // cabin details have already been parsed as well: the segment cabin
00320       // can thus be added to the segment.
00321       if (_flightPeriod._areSegmentDefinitionsSpecific == true) {
00322         _flightPeriod.addSegmentCabin (_flightPeriod._itSegment,
00323                                        _flightPeriod._itSegmentCabin);
00324       } else {
00325         _flightPeriod.addSegmentCabin (_flightPeriod._itSegmentCabin);
00326       }
00327     }
00328 
00329     // //////////////////////////////////////////////////////////////////
00330     storeFamilyCode::
00331     storeFamilyCode (FlightPeriodStruct& ioFlightPeriod)
00332       : ParserSemanticAction (ioFlightPeriod) {
00333     }
00334     
00335     // //////////////////////////////////////////////////////////////////
00336     void storeFamilyCode::operator() (int iCode) const {
00337       std::ostringstream ostr;
00338       ostr << iCode;
00339       _flightPeriod._itSegmentCabin._itFamilyCode = ostr.str(); 
00340     }
00341 
00342     // //////////////////////////////////////////////////////////////////
00343     storeFClasses::
00344     storeFClasses (FlightPeriodStruct& ioFlightPeriod)
00345       : ParserSemanticAction (ioFlightPeriod) {
00346     }
00347 
00348     // //////////////////////////////////////////////////////////////////
00349     void storeFClasses::operator() (iterator_t iStr,
00350                                     iterator_t iStrEnd) const {
00351       std::string lClasses (iStr, iStrEnd);
00352       FareFamilyStruct lFareFamily(_flightPeriod._itSegmentCabin._itFamilyCode,
00353                                      lClasses);
00354 
00355       // The list of classes is the last (according to the arrival order
00356       // within the schedule input file) detail of the segment cabin. Hence,
00357       // when a list of classes is parsed, it means that the full segment
00358       // cabin details have already been parsed as well: the segment cabin
00359       // can thus be added to the segment.
00360       if (_flightPeriod._areSegmentDefinitionsSpecific == true) {
00361         _flightPeriod.addFareFamily (_flightPeriod._itSegment,
00362                                      _flightPeriod._itSegmentCabin,
00363                                      lFareFamily);
00364       } else {
00365         _flightPeriod.addFareFamily (_flightPeriod._itSegmentCabin,
00366                                      lFareFamily);
00367       }
00368     }
00369 
00370     // //////////////////////////////////////////////////////////////////
00371     doEndFlight::
00372     doEndFlight (stdair::BomRoot& ioBomRoot,
00373                  FlightPeriodStruct& ioFlightPeriod)
00374       : ParserSemanticAction (ioFlightPeriod),
00375         _bomRoot (ioBomRoot) {
00376     }
00377     
00378     // //////////////////////////////////////////////////////////////////
00379     // void doEndFlight::operator() (char iChar) const {
00380     void doEndFlight::operator() (iterator_t iStr,
00381                                   iterator_t iStrEnd) const {
00382 
00383       assert (_flightPeriod._legAlreadyDefined == true);
00384       _flightPeriod._legList.push_back (_flightPeriod._itLeg);
00385         
00386       // The lists of legs and cabins must be reset
00387       _flightPeriod._legAlreadyDefined = false;
00388       _flightPeriod._itLeg._cabinList.clear();
00389         
00390       // DEBUG: Display the result
00391       STDAIR_LOG_DEBUG ("FlightPeriod: " << _flightPeriod.describe());
00392 
00393       // Create the FlightPeriod BOM objects, and potentially the intermediary
00394       // objects (e.g., Inventory).
00395       InventoryGenerator::createFlightPeriod (_bomRoot, _flightPeriod);
00396     }
00397 
00398       
00399     // ///////////////////////////////////////////////////////////////////
00400     //
00401     //  Utility Parsers
00402     //
00403     // ///////////////////////////////////////////////////////////////////
00405     int1_p_t int1_p;
00406     
00408     uint2_p_t uint2_p;
00409     
00411     uint4_p_t uint4_p;
00412     
00414     uint1_4_p_t uint1_4_p;
00415 
00417     repeat_p_t airline_code_p (chset_t("0-9A-Z").derived(), 2, 3);
00418       
00420     bounded1_4_p_t flight_number_p (uint1_4_p.derived(), 0u, 9999u);
00421 
00423     bounded4_p_t year_p (uint4_p.derived(), 2000u, 2099u);
00424       
00426     bounded2_p_t month_p (uint2_p.derived(), 1u, 12u);
00427 
00429     bounded2_p_t day_p (uint2_p.derived(), 1u, 31u);
00430      
00432     repeat_p_t dow_p (chset_t("0-1").derived().derived(), 7, 7);
00433 
00435     repeat_p_t airport_p (chset_t("0-9A-Z").derived(), 3, 3);
00436       
00438     bounded2_p_t hours_p (uint2_p.derived(), 0u, 23u);
00439 
00441     bounded2_p_t minutes_p (uint2_p.derived(), 0u, 59u);
00442 
00444     bounded2_p_t seconds_p (uint2_p.derived(), 0u, 59u);
00445 
00447     chset_t cabin_code_p ("A-Z");
00448 
00450     int1_p_t family_code_p;
00451       
00453     repeat_p_t class_code_list_p (chset_t("A-Z").derived(), 1, 26);
00454 
00455 
00456     // //////////////////////////////////////////////////////////////////
00457     //  (Boost Spirit) Grammar Definition
00458     // //////////////////////////////////////////////////////////////////
00459 
00460     // //////////////////////////////////////////////////////////////////
00461     FlightPeriodParser::
00462     FlightPeriodParser (stdair::BomRoot& ioBomRoot,
00463                         FlightPeriodStruct& ioFlightPeriod) 
00464       : _bomRoot (ioBomRoot),
00465         _flightPeriod (ioFlightPeriod) {
00466     }
00467 
00468     // //////////////////////////////////////////////////////////////////
00469     template<typename ScannerT>
00470     FlightPeriodParser::definition<ScannerT>::
00471     definition (FlightPeriodParser const& self) {
00472 
00473       flight_period_list = *( boost::spirit::classic::comment_p("//")
00474                               | boost::spirit::classic::comment_p("/*", "*/")
00475                               | flight_period )
00476         ;
00477       
00478       flight_period = flight_key
00479         >> +( ';' >> leg )
00480         >> ';' >> segment_section
00481         >> flight_period_end[doEndFlight (self._bomRoot, self._flightPeriod)]
00482         ;
00483 
00484       flight_period_end =
00485         boost::spirit::classic::ch_p(';')
00486         ;
00487       
00488       flight_key = airline_code
00489         >> ';' >> flight_number
00490         >> ';' >> date[storeDateRangeStart(self._flightPeriod)]
00491         >> ';' >> date[storeDateRangeEnd(self._flightPeriod)]
00492         >> ';' >> dow[storeDow(self._flightPeriod)]
00493         ;
00494 
00495       airline_code = boost::spirit::classic::
00496         lexeme_d[(airline_code_p)[storeAirlineCode(self._flightPeriod)] ]
00497         ;
00498         
00499       flight_number = boost::spirit::classic::
00500         lexeme_d[(flight_number_p)[storeFlightNumber(self._flightPeriod)] ]
00501         ;
00502 
00503       date = boost::spirit::classic::
00504         lexeme_d[(year_p)[boost::spirit::classic::
00505                           assign_a(self._flightPeriod._itYear)]
00506                  >> '-'
00507                  >> (month_p)[boost::spirit::classic::
00508                               assign_a(self._flightPeriod._itMonth)]
00509                  >> '-'
00510                  >> (day_p)[boost::spirit::classic::
00511                             assign_a(self._flightPeriod._itDay)]
00512                  ]
00513         ;
00514 
00515       dow = boost::spirit::classic::lexeme_d[ dow_p ]
00516         ;
00517       
00518       leg = leg_key >> ';' >> leg_details >> +( ';' >> leg_cabin_details )
00519         ;
00520          
00521       leg_key =
00522         (airport_p)[storeLegBoardingPoint(self._flightPeriod)]
00523         >> ';'
00524         >> (airport_p)[storeLegOffPoint(self._flightPeriod)]
00525         ;
00526          
00527       leg_details =
00528         time[storeBoardingTime(self._flightPeriod)]
00529         >> !(date_offset)
00530         >> ';'
00531         >> time[storeOffTime(self._flightPeriod)]
00532         >> !(date_offset)
00533         >> ';'
00534         >> time[storeElapsedTime(self._flightPeriod)]
00535         ;
00536         
00537       time = boost::spirit::classic::
00538         lexeme_d[(hours_p)[boost::spirit::classic::
00539                            assign_a(self._flightPeriod._itHours)]
00540                  >> ':'
00541                  >> (minutes_p)[boost::spirit::classic::
00542                                 assign_a(self._flightPeriod._itMinutes)]
00543                  >> !(':' 
00544                       >> (seconds_p)[boost::spirit::classic::
00545                                      assign_a(self._flightPeriod._itSeconds)])
00546                  ]
00547         ;
00548 
00549       date_offset = boost::spirit::classic::ch_p('/')
00550         >> (int1_p)[boost::spirit::classic::
00551                     assign_a(self._flightPeriod._dateOffset)]
00552         ;          
00553         
00554       leg_cabin_details = (cabin_code_p)[storeLegCabinCode(self._flightPeriod)]
00555         >> ';' >> (boost::spirit::classic::
00556                    ureal_p)[storeCapacity(self._flightPeriod)]
00557         ;
00558         
00559       segment_key =
00560         (airport_p)[storeSegmentBoardingPoint(self._flightPeriod)]
00561         >> ';'
00562         >> (airport_p)[storeSegmentOffPoint(self._flightPeriod)]
00563         ;
00564          
00565       segment_section =
00566         generic_segment | specific_segment_list
00567         ;
00568 
00569       generic_segment = boost::spirit::classic::
00570         ch_p('0')[storeSegmentSpecificity(self._flightPeriod)]
00571         >> +(';' >> segment_cabin_details)
00572         ;
00573 
00574       specific_segment_list = boost::spirit::classic::
00575         ch_p('1')[storeSegmentSpecificity(self._flightPeriod)]
00576         >> +(';' >> segment_key >> full_segment_cabin_details)
00577         ;
00578 
00579       full_segment_cabin_details =
00580         +(';' >> segment_cabin_details)
00581         ;
00582 
00583       segment_cabin_details =
00584         (cabin_code_p)[storeSegmentCabinCode(self._flightPeriod)]
00585         >> ';' >> (class_code_list_p)[storeClasses(self._flightPeriod)]
00586         >> *(';' >> family_cabin_details)
00587         ;
00588 
00589       family_cabin_details =
00590         (family_code_p)[storeFamilyCode(self._flightPeriod)]
00591         >> ';'
00592         >> (class_code_list_p)[storeFClasses(self._flightPeriod)]
00593         ;
00594         
00595       // BOOST_SPIRIT_DEBUG_NODE (FlightPeriodParser);
00596       BOOST_SPIRIT_DEBUG_NODE (flight_period_list);
00597       BOOST_SPIRIT_DEBUG_NODE (flight_period);
00598       BOOST_SPIRIT_DEBUG_NODE (flight_period_end);
00599       BOOST_SPIRIT_DEBUG_NODE (flight_key);
00600       BOOST_SPIRIT_DEBUG_NODE (airline_code);
00601       BOOST_SPIRIT_DEBUG_NODE (flight_number);
00602       BOOST_SPIRIT_DEBUG_NODE (date);
00603       BOOST_SPIRIT_DEBUG_NODE (dow);
00604       BOOST_SPIRIT_DEBUG_NODE (leg);
00605       BOOST_SPIRIT_DEBUG_NODE (leg_key);
00606       BOOST_SPIRIT_DEBUG_NODE (leg_details);
00607       BOOST_SPIRIT_DEBUG_NODE (time);
00608       BOOST_SPIRIT_DEBUG_NODE (date_offset);
00609       BOOST_SPIRIT_DEBUG_NODE (leg_cabin_details);
00610       BOOST_SPIRIT_DEBUG_NODE (segment_section);
00611       BOOST_SPIRIT_DEBUG_NODE (segment_key);
00612       BOOST_SPIRIT_DEBUG_NODE (generic_segment);
00613       BOOST_SPIRIT_DEBUG_NODE (specific_segment_list);
00614       BOOST_SPIRIT_DEBUG_NODE (full_segment_cabin_details);
00615       BOOST_SPIRIT_DEBUG_NODE (segment_cabin_details);
00616       BOOST_SPIRIT_DEBUG_NODE (family_cabin_details);
00617     }
00618 
00619     // //////////////////////////////////////////////////////////////////
00620     template<typename ScannerT>
00621     boost::spirit::classic::rule<ScannerT> const&
00622     FlightPeriodParser::definition<ScannerT>::start() const {
00623       return flight_period_list;
00624     }
00625     
00626   }
00627 
00628 
00630   //
00631   //  Entry class for the file parser
00632   //
00634 
00635   // //////////////////////////////////////////////////////////////////////
00636   FlightPeriodFileParser::
00637   FlightPeriodFileParser (stdair::BomRoot& ioBomRoot,
00638                           const stdair::Filename_T& iFilename)
00639     : _filename (iFilename), _bomRoot (ioBomRoot) {
00640     init();
00641   }
00642 
00643   // //////////////////////////////////////////////////////////////////////
00644   void FlightPeriodFileParser::init() {
00645     // Check that the file exists and is readable
00646     const bool doesExistAndIsReadable =
00647       stdair::BasFileMgr::doesExistAndIsReadable (_filename);
00648 
00649     if (doesExistAndIsReadable == false) {
00650       STDAIR_LOG_ERROR ("The schedule file " << _filename
00651                         << " does not exist or can not be read.");
00652       
00653       throw ScheduleInputFileNotFoundException ("The schedule file " + _filename
00654                                                 + " does not exist or can not be read");
00655     }
00656     
00657     // Open the file
00658     _startIterator = iterator_t (_filename);
00659 
00660     // Check the filename exists and can be open
00661     if (!_startIterator) {
00662       STDAIR_LOG_ERROR ("The schedule file " << _filename << " can not be open."
00663                           << std::endl);
00664 
00665       throw ScheduleInputFileNotFoundException ("The file " + _filename
00666                                                 + " does not exist or can not be read");
00667     }
00668 
00669     // Create an EOF iterator
00670     _endIterator = _startIterator.make_end();
00671   }
00672     
00673   // //////////////////////////////////////////////////////////////////////
00674   bool FlightPeriodFileParser::generateInventories () {
00675     bool oResult = false;
00676       
00677     STDAIR_LOG_DEBUG ("Parsing schedule input file: " << _filename);
00678 
00679     // Initialise the parser (grammar) with the helper/staging structure.
00680     ScheduleParserHelper::FlightPeriodParser lFPParser (_bomRoot, 
00681                                                         _flightPeriod);
00682       
00683     // Launch the parsing of the file and, thanks to the doEndFlight
00684     // call-back structure, the building of the whole BomRoot BOM
00685     // (i.e., including Inventory, FlightDate, LegDate, SegmentDate, etc.)
00686     boost::spirit::classic::parse_info<iterator_t> info =
00687       boost::spirit::classic::parse (_startIterator, _endIterator, lFPParser, 
00688                             boost::spirit::classic::space_p);
00689 
00690     // Retrieves whether or not the parsing was successful
00691     oResult = info.hit;
00692       
00693     const std::string hasBeenFullyReadStr = (info.full == true)?"":"not ";
00694     if (oResult == true) {
00695       STDAIR_LOG_DEBUG ("Parsing of schedule input file: " << _filename
00696                        << " succeeded: read " << info.length
00697                        << " characters. The input file has "
00698                        << hasBeenFullyReadStr
00699                        << "been fully read. Stop point: " << info.stop);
00700         
00701     } else {
00702       // TODO: decide whether to throw an exception
00703       STDAIR_LOG_ERROR ("Parsing of schedule input file: " << _filename
00704                        << " failed: read " << info.length
00705                        << " characters. The input file has "
00706                        << hasBeenFullyReadStr
00707                        << "been fully read. Stop point: " << info.stop);
00708     }
00709 
00710     return oResult;
00711   }
00712     
00713 }