$treeview $search $mathjax
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/OnDParserHelper.hpp> 00012 #include <airsched/command/OnDPeriodGenerator.hpp> 00013 00014 namespace AIRSCHED { 00015 00016 namespace OnDParserHelper { 00017 00018 // ////////////////////////////////////////////////////////////////////// 00019 // 00020 // Semantic actions 00021 // 00022 // ////////////////////////////////////////////////////////////////////// 00023 00024 ParserSemanticAction:: 00025 ParserSemanticAction (OnDPeriodStruct& ioOnDPeriod) 00026 : _onDPeriod (ioOnDPeriod) { 00027 } 00028 00029 // ////////////////////////////////////////////////////////////////////// 00030 storeOrigin::storeOrigin (OnDPeriodStruct& ioOnDPeriod) 00031 : ParserSemanticAction (ioOnDPeriod) { 00032 } 00033 00034 // ////////////////////////////////////////////////////////////////////// 00035 void storeOrigin::operator() (iterator_t iStr, 00036 iterator_t iStrEnd) const { 00037 std::string lOrigin (iStr, iStrEnd); 00038 //STDAIR_LOG_DEBUG ( "Origin: " << lOrigin << std::endl); 00039 00040 // Set the origin 00041 _onDPeriod._origin = lOrigin; 00042 _onDPeriod._nbOfAirlines = 0; 00043 _onDPeriod._airlineCode = ""; 00044 _onDPeriod._classCode = ""; 00045 _onDPeriod._airlineCodeList.clear(); 00046 _onDPeriod._classCodeList.clear(); 00047 } 00048 00049 // ////////////////////////////////////////////////////////////////////// 00050 storeDestination::storeDestination (OnDPeriodStruct& ioOnDPeriod) 00051 : ParserSemanticAction (ioOnDPeriod) { 00052 } 00053 00054 // ////////////////////////////////////////////////////////////////////// 00055 void storeDestination::operator() (iterator_t iStr, 00056 iterator_t iStrEnd) const { 00057 std::string lDestination (iStr, iStrEnd); 00058 //STDAIR_LOG_DEBUG ("Destination: " << lDestination << std::endl); 00059 00060 // Set the destination 00061 _onDPeriod._destination = lDestination; 00062 } 00063 00064 // ////////////////////////////////////////////////////////////////////// 00065 storeDateRangeStart:: 00066 storeDateRangeStart (OnDPeriodStruct& ioOnDPeriod) 00067 : ParserSemanticAction (ioOnDPeriod) { 00068 } 00069 00070 // ////////////////////////////////////////////////////////////////////// 00071 void storeDateRangeStart::operator() (iterator_t iStr, 00072 iterator_t iStrEnd) const { 00073 _onDPeriod._dateRangeStart = _onDPeriod.getDate(); 00074 /*STDAIR_LOG_DEBUG ("Date Range Start: " 00075 << _onDPeriod._dateRangeStart << std::endl);*/ 00076 00077 // Reset the number of seconds 00078 _onDPeriod._itSeconds = 0; 00079 } 00080 00081 // ////////////////////////////////////////////////////////////////////// 00082 storeDateRangeEnd:: 00083 storeDateRangeEnd (OnDPeriodStruct& ioOnDPeriod) 00084 : ParserSemanticAction (ioOnDPeriod) { 00085 } 00086 00087 // ////////////////////////////////////////////////////////////////////// 00088 void storeDateRangeEnd::operator() (iterator_t iStr, 00089 iterator_t iStrEnd) const { 00090 // As a Boost date period (COM::DatePeriod_T) defines the last day of 00091 // the period to be end-date - one day, we have to add one day to that 00092 // end date before. 00093 const stdair::DateOffset_T oneDay (1); 00094 _onDPeriod._dateRangeEnd = _onDPeriod.getDate() + oneDay; 00095 /*STDAIR_LOG_DEBUG ( "Date Range End: " 00096 << _onDPeriod._dateRangeEnd << std::endl);*/ 00097 00098 // Transform the date pair (i.e., the date range) into a date period 00099 _onDPeriod._datePeriod = 00100 stdair::DatePeriod_T (_onDPeriod._dateRangeStart, 00101 _onDPeriod._dateRangeEnd); 00102 00103 // Reset the number of seconds 00104 _onDPeriod._itSeconds = 0; 00105 } 00106 00107 // ////////////////////////////////////////////////////////////////////// 00108 storeStartRangeTime:: 00109 storeStartRangeTime (OnDPeriodStruct& ioOnDPeriod) 00110 : ParserSemanticAction (ioOnDPeriod) { 00111 } 00112 00113 // ////////////////////////////////////////////////////////////////////// 00114 void storeStartRangeTime::operator() (iterator_t iStr, 00115 iterator_t iStrEnd) const { 00116 _onDPeriod._timeRangeStart = _onDPeriod.getTime(); 00117 00118 // Reset the number of seconds 00119 _onDPeriod._itSeconds = 0; 00120 } 00121 00122 // ////////////////////////////////////////////////////////////////////// 00123 storeEndRangeTime:: 00124 storeEndRangeTime (OnDPeriodStruct& ioOnDPeriod) 00125 : ParserSemanticAction (ioOnDPeriod) { 00126 } 00127 00128 // ////////////////////////////////////////////////////////////////////// 00129 void storeEndRangeTime::operator() (iterator_t iStr, 00130 iterator_t iStrEnd) const { 00131 _onDPeriod._timeRangeEnd = _onDPeriod.getTime(); 00132 00133 // Reset the number of seconds 00134 _onDPeriod._itSeconds = 0; 00135 } 00136 00137 // ////////////////////////////////////////////////////////////////////// 00138 storeAirlineCode:: 00139 storeAirlineCode (OnDPeriodStruct& ioOnDPeriod) 00140 : ParserSemanticAction (ioOnDPeriod) { 00141 } 00142 00143 // ////////////////////////////////////////////////////////////////////// 00144 void storeAirlineCode::operator() (iterator_t iStr, 00145 iterator_t iStrEnd) const { 00146 const std::string lAirlineCodeStr (iStr, iStrEnd); 00147 const stdair::AirlineCode_T lAirlineCode(lAirlineCodeStr); 00148 // Test if the OnD Period Struct stands for interline products 00149 if (_onDPeriod._airlineCodeList.size() > 0) { 00150 // update the airline code 00151 std::ostringstream ostr; 00152 ostr << _onDPeriod._airlineCode << lAirlineCode; 00153 _onDPeriod._airlineCode = ostr.str(); 00154 // Update the number of airlines if necessary 00155 const stdair::AirlineCode_T lPreviousAirlineCode = 00156 _onDPeriod._airlineCodeList.back(); 00157 if (lPreviousAirlineCode != lAirlineCode) { 00158 _onDPeriod._nbOfAirlines = _onDPeriod._nbOfAirlines + 1; 00159 } 00160 } 00161 else { 00162 _onDPeriod._airlineCode = lAirlineCode; 00163 _onDPeriod._nbOfAirlines = 1; 00164 } 00165 _onDPeriod._airlineCodeList.push_back (lAirlineCode); 00166 00167 //STDAIR_LOG_DEBUG ( "Airline code: " << lAirlineCode << std::endl); 00168 } 00169 00170 // ////////////////////////////////////////////////////////////////////// 00171 storeClassCode:: 00172 storeClassCode (OnDPeriodStruct& ioOnDPeriod) 00173 : ParserSemanticAction (ioOnDPeriod) { 00174 } 00175 00176 // ////////////////////////////////////////////////////////////////////// 00177 void storeClassCode::operator() (char iChar) const { 00178 std::ostringstream ostr; 00179 ostr << iChar; 00180 std::string classCodeStr = ostr.str(); 00181 const stdair::ClassCode_T lClassCode (classCodeStr); 00182 _onDPeriod._classCodeList.push_back(lClassCode); 00183 /*STDAIR_LOG_DEBUG ("Class Code: " 00184 << lClassCode << std::endl);*/ 00185 // Insertion of this class Code in the whole classCode name 00186 std::ostringstream ostrr; 00187 ostrr << _onDPeriod._classCode << classCodeStr; 00188 _onDPeriod._classCode = ostrr.str(); 00189 00190 } 00191 00192 // ////////////////////////////////////////////////////////////////////// 00193 doEndOnD::doEndOnD (stdair::BomRoot& ioBomRoot, OnDPeriodStruct& ioOnDPeriod) 00194 : ParserSemanticAction (ioOnDPeriod), 00195 _bomRoot (ioBomRoot) { 00196 } 00197 00198 // ////////////////////////////////////////////////////////////////////// 00199 void doEndOnD::operator() (iterator_t iStr, iterator_t iStrEnd) const { 00200 00201 // DEBUG: Display the result 00202 // STDAIR_LOG_DEBUG ("FareRule " << _onDPeriod.describe()); 00203 00204 // Generation of the O&D-Period object. 00205 OnDPeriodGenerator::createOnDPeriod (_bomRoot, _onDPeriod); 00206 } 00207 00208 // /////////////////////////////////////////////////////////////////////// 00209 // 00210 // Utility Parsers 00211 // 00212 // /////////////////////////////////////////////////////////////////////// 00213 00215 uint2_p_t uint2_p; 00216 00218 uint4_p_t uint4_p; 00219 00221 uint1_4_p_t uint1_4_p; 00222 00224 chset_t alpha_cap_set_p ("A-Z"); 00225 00227 repeat_p_t airport_p (chset_t("0-9A-Z").derived(), 3, 3); 00228 00230 repeat_p_t airline_code_p (alpha_cap_set_p.derived(), 2, 3); 00231 00233 bounded4_p_t year_p (uint4_p.derived(), 2000u, 2099u); 00234 00236 bounded2_p_t month_p (uint2_p.derived(), 1u, 12u); 00237 00239 bounded2_p_t day_p (uint2_p.derived(), 1u, 31u); 00240 00242 bounded2_p_t hours_p (uint2_p.derived(), 0u, 23u); 00243 00245 bounded2_p_t minutes_p (uint2_p.derived(), 0u, 59u); 00246 00248 bounded2_p_t seconds_p (uint2_p.derived(), 0u, 59u); 00249 00251 chset_t class_code_p ("A-Z"); 00252 00254 // 00255 // (Boost Spirit) Grammar Definition 00256 // 00258 00259 // ////////////////////////////////////////////////////////////////////// 00260 OnDParser:: 00261 OnDParser (stdair::BomRoot& ioBomRoot, OnDPeriodStruct& ioOnDPeriod) 00262 : _bomRoot (ioBomRoot), _onDPeriod (ioOnDPeriod) { 00263 } 00264 00265 // ////////////////////////////////////////////////////////////////////// 00266 template<typename ScannerT> 00267 OnDParser::definition<ScannerT>::definition (OnDParser const& self) { 00268 00269 ond_list = *( boost::spirit::classic::comment_p("//") 00270 | boost::spirit::classic::comment_p("/*", "*/") 00271 | ond ) 00272 ; 00273 00274 ond = ond_key 00275 >> +( ';' >> segment ) 00276 >> ond_end[doEndOnD(self._bomRoot, self._onDPeriod)] 00277 ; 00278 00279 ond_end = boost::spirit::classic::ch_p(';') 00280 ; 00281 00282 ond_key = (airport_p)[storeOrigin(self._onDPeriod)] 00283 >> ';' >> (airport_p)[storeDestination(self._onDPeriod)] 00284 >> ';' >> date[storeDateRangeStart(self._onDPeriod)] 00285 >> ';' >> date[storeDateRangeEnd(self._onDPeriod)] 00286 >> ';' >> time[storeStartRangeTime(self._onDPeriod)] 00287 >> ';' >> time[storeEndRangeTime(self._onDPeriod)] 00288 ; 00289 00290 date = boost::spirit::classic:: 00291 lexeme_d[(year_p)[boost::spirit::classic:: 00292 assign_a(self._onDPeriod._itYear)] 00293 >> '-' 00294 >> (month_p)[boost::spirit::classic:: 00295 assign_a(self._onDPeriod._itMonth)] 00296 >> '-' 00297 >> (day_p)[boost::spirit::classic:: 00298 assign_a(self._onDPeriod._itDay)]] 00299 ; 00300 00301 time = boost::spirit::classic:: 00302 lexeme_d[(hours_p)[boost::spirit::classic:: 00303 assign_a(self._onDPeriod._itHours)] 00304 >> ':' 00305 >> (minutes_p)[boost::spirit::classic:: 00306 assign_a(self._onDPeriod._itMinutes)] 00307 >> !(':' >> (seconds_p)[boost::spirit::classic:: 00308 assign_a(self._onDPeriod._itSeconds)])] 00309 ; 00310 00311 segment = boost::spirit::classic:: 00312 lexeme_d[(airline_code_p)[storeAirlineCode(self._onDPeriod)]] 00313 >> ';' >> (class_code_p)[storeClassCode(self._onDPeriod)] 00314 ; 00315 00316 //BOOST_SPIRIT_DEBUG_NODE (OnDParser); 00317 BOOST_SPIRIT_DEBUG_NODE (ond_list); 00318 BOOST_SPIRIT_DEBUG_NODE (ond); 00319 BOOST_SPIRIT_DEBUG_NODE (segment); 00320 BOOST_SPIRIT_DEBUG_NODE (ond_key); 00321 BOOST_SPIRIT_DEBUG_NODE (ond_end); 00322 BOOST_SPIRIT_DEBUG_NODE (date); 00323 BOOST_SPIRIT_DEBUG_NODE (time); 00324 00325 } 00326 00327 // ////////////////////////////////////////////////////////////////////// 00328 template<typename ScannerT> 00329 boost::spirit::classic::rule<ScannerT> const& 00330 OnDParser::definition<ScannerT>::start() const { 00331 return ond_list; 00332 } 00333 } 00334 00336 // 00337 // Entry class for the file parser 00338 // 00340 00341 // ////////////////////////////////////////////////////////////////////// 00342 OnDPeriodFileParser::OnDPeriodFileParser (const stdair::Filename_T& iFilename, 00343 stdair::BomRoot& ioBomRoot) 00344 : _filename (iFilename), _bomRoot (ioBomRoot) { 00345 init(); 00346 } 00347 00348 // ////////////////////////////////////////////////////////////////////// 00349 void OnDPeriodFileParser::init() { 00350 // Check that the file exists and is readable 00351 const bool doesExistAndIsReadable = 00352 stdair::BasFileMgr::doesExistAndIsReadable (_filename); 00353 00354 if (doesExistAndIsReadable == false) { 00355 STDAIR_LOG_ERROR ("The O&D file " << _filename 00356 << " does not exist or can not be read."); 00357 00358 throw OnDInputFileNotFoundException ("The O&D file " + _filename 00359 + " does not exist or can not be read"); 00360 } 00361 00362 // Open the file 00363 _startIterator = iterator_t (_filename); 00364 00365 // Check that the filename exists and can be open 00366 if (!_startIterator) { 00367 STDAIR_LOG_DEBUG ("The O&D file " << _filename << " can not be open." 00368 << std::endl); 00369 throw OnDInputFileNotFoundException ("The file " + _filename 00370 + " does not exist or can not be read"); 00371 } 00372 00373 // Create an EOF iterator 00374 _endIterator = _startIterator.make_end(); 00375 } 00376 00377 // ////////////////////////////////////////////////////////////////////// 00378 bool OnDPeriodFileParser::generateOnDPeriods () { 00379 bool oResult = false; 00380 00381 STDAIR_LOG_DEBUG ("Parsing O&D input file: " << _filename); 00382 00383 // Initialise the parser (grammar) with the helper/staging structure. 00384 OnDParserHelper::OnDParser lODParser (_bomRoot, _onDPeriod); 00385 00386 // Launch the parsing of the file and, thanks to the doEndOnD 00387 // call-back structure, filling the worldSchedule (Fares) 00388 boost::spirit::classic::parse_info<iterator_t> info = 00389 boost::spirit::classic::parse (_startIterator, _endIterator, lODParser, 00390 boost::spirit::classic::space_p); 00391 00392 // Retrieves whether or not the parsing was successful 00393 oResult = info.hit; 00394 00395 const std::string hasBeenFullyReadStr = (info.full == true)?"":"not "; 00396 if (oResult == true) { 00397 STDAIR_LOG_DEBUG ("Parsing of O&D input file: " << _filename 00398 << " succeeded: read " << info.length 00399 << " characters. The input file has " 00400 << hasBeenFullyReadStr 00401 << "been fully read. Stop point: " << info.stop); 00402 00403 } else { 00404 // TODO: decide whether to throw an exception 00405 STDAIR_LOG_ERROR ("Parsing of O&D input file: " << _filename 00406 << " failed: read " << info.length 00407 << " characters. The input file has " 00408 << hasBeenFullyReadStr 00409 << "been fully read. Stop point: " << info.stop); 00410 } 00411 00412 return oResult; 00413 } 00414 }