AirTSP Logo  1.01.0
C++ Simulated Airline Travel Solution Provider Library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
OnDParserHelper.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // STL
5 #include <cassert>
6 // StdAir
7 #include <stdair/basic/BasFileMgr.hpp>
8 #include <stdair/bom/BomRoot.hpp>
9 #include <stdair/service/Logger.hpp>
10 // AirTSP
13 
14 namespace AIRTSP {
15 
16  namespace OnDParserHelper {
17 
18  // //////////////////////////////////////////////////////////////////////
19  //
20  // Semantic actions
21  //
22  // //////////////////////////////////////////////////////////////////////
23 
26  : _onDPeriod (ioOnDPeriod) {
27  }
28 
29  // //////////////////////////////////////////////////////////////////////
31  : ParserSemanticAction (ioOnDPeriod) {
32  }
33 
34  // //////////////////////////////////////////////////////////////////////
36  iterator_t iStrEnd) const {
37  std::string lOrigin (iStr, iStrEnd);
38  //STDAIR_LOG_DEBUG ( "Origin: " << lOrigin << std::endl);
39 
40  // Set the origin
41  _onDPeriod._origin = lOrigin;
46  _onDPeriod._classCodeList.clear();
47  }
48 
49  // //////////////////////////////////////////////////////////////////////
51  : ParserSemanticAction (ioOnDPeriod) {
52  }
53 
54  // //////////////////////////////////////////////////////////////////////
56  iterator_t iStrEnd) const {
57  std::string lDestination (iStr, iStrEnd);
58  //STDAIR_LOG_DEBUG ("Destination: " << lDestination << std::endl);
59 
60  // Set the destination
61  _onDPeriod._destination = lDestination;
62  }
63 
64  // //////////////////////////////////////////////////////////////////////
67  : ParserSemanticAction (ioOnDPeriod) {
68  }
69 
70  // //////////////////////////////////////////////////////////////////////
72  iterator_t iStrEnd) const {
74  /*STDAIR_LOG_DEBUG ("Date Range Start: "
75  << _onDPeriod._dateRangeStart << std::endl);*/
76 
77  // Reset the number of seconds
79  }
80 
81  // //////////////////////////////////////////////////////////////////////
84  : ParserSemanticAction (ioOnDPeriod) {
85  }
86 
87  // //////////////////////////////////////////////////////////////////////
89  iterator_t iStrEnd) const {
90  // As a Boost date period (COM::DatePeriod_T) defines the last day of
91  // the period to be end-date - one day, we have to add one day to that
92  // end date before.
93  const stdair::DateOffset_T oneDay (1);
95  /*STDAIR_LOG_DEBUG ( "Date Range End: "
96  << _onDPeriod._dateRangeEnd << std::endl);*/
97 
98  // Transform the date pair (i.e., the date range) into a date period
100  stdair::DatePeriod_T (_onDPeriod._dateRangeStart,
102 
103  // Reset the number of seconds
105  }
106 
107  // //////////////////////////////////////////////////////////////////////
110  : ParserSemanticAction (ioOnDPeriod) {
111  }
112 
113  // //////////////////////////////////////////////////////////////////////
115  iterator_t iStrEnd) const {
117 
118  // Reset the number of seconds
120  }
121 
122  // //////////////////////////////////////////////////////////////////////
125  : ParserSemanticAction (ioOnDPeriod) {
126  }
127 
128  // //////////////////////////////////////////////////////////////////////
130  iterator_t iStrEnd) const {
132 
133  // Reset the number of seconds
135  }
136 
137  // //////////////////////////////////////////////////////////////////////
140  : ParserSemanticAction (ioOnDPeriod) {
141  }
142 
143  // //////////////////////////////////////////////////////////////////////
145  iterator_t iStrEnd) const {
146  const std::string lAirlineCodeStr (iStr, iStrEnd);
147  const stdair::AirlineCode_T lAirlineCode(lAirlineCodeStr);
148  // Test if the OnD Period Struct stands for interline products
149  if (_onDPeriod._airlineCodeList.size() > 0) {
150  // update the airline code
151  std::ostringstream ostr;
152  ostr << _onDPeriod._airlineCode << lAirlineCode;
153  _onDPeriod._airlineCode = ostr.str();
154  // Update the number of airlines if necessary
155  const stdair::AirlineCode_T lPreviousAirlineCode =
157  if (lPreviousAirlineCode != lAirlineCode) {
159  }
160  }
161  else {
162  _onDPeriod._airlineCode = lAirlineCode;
164  }
165  _onDPeriod._airlineCodeList.push_back (lAirlineCode);
166 
167  //STDAIR_LOG_DEBUG ( "Airline code: " << lAirlineCode << std::endl);
168  }
169 
170  // //////////////////////////////////////////////////////////////////////
173  : ParserSemanticAction (ioOnDPeriod) {
174  }
175 
176  // //////////////////////////////////////////////////////////////////////
177  void storeClassCode::operator() (char iChar) const {
178  std::ostringstream ostr;
179  ostr << iChar;
180  std::string classCodeStr = ostr.str();
181  const stdair::ClassCode_T lClassCode (classCodeStr);
182  _onDPeriod._classCodeList.push_back(lClassCode);
183  /*STDAIR_LOG_DEBUG ("Class Code: "
184  << lClassCode << std::endl);*/
185  // Insertion of this class Code in the whole classCode name
186  std::ostringstream ostrr;
187  ostrr << _onDPeriod._classCode << classCodeStr;
188  _onDPeriod._classCode = ostrr.str();
189 
190  }
191 
192  // //////////////////////////////////////////////////////////////////////
193  doEndOnD::doEndOnD (stdair::BomRoot& ioBomRoot, OnDPeriodStruct& ioOnDPeriod)
194  : ParserSemanticAction (ioOnDPeriod),
195  _bomRoot (ioBomRoot) {
196  }
197 
198  // //////////////////////////////////////////////////////////////////////
199  void doEndOnD::operator() (iterator_t iStr, iterator_t iStrEnd) const {
200 
201  // DEBUG: Display the result
202  // STDAIR_LOG_DEBUG ("FareRule " << _onDPeriod.describe());
203 
204  // Generation of the O&D-Period object.
205  OnDPeriodGenerator::createOnDPeriod (_bomRoot, _onDPeriod);
206  }
207 
208  // ///////////////////////////////////////////////////////////////////////
209  //
210  // Utility Parsers
211  //
212  // ///////////////////////////////////////////////////////////////////////
213 
216 
219 
222 
224  chset_t alpha_cap_set_p ("A-Z");
225 
227  repeat_p_t airport_p (chset_t("0-9A-Z").derived(), 3, 3);
228 
230  repeat_p_t airline_code_p (alpha_cap_set_p.derived(), 2, 3);
231 
233  bounded4_p_t year_p (uint4_p.derived(), 2000u, 2099u);
234 
236  bounded2_p_t month_p (uint2_p.derived(), 1u, 12u);
237 
239  bounded2_p_t day_p (uint2_p.derived(), 1u, 31u);
240 
242  bounded2_p_t hours_p (uint2_p.derived(), 0u, 23u);
243 
245  bounded2_p_t minutes_p (uint2_p.derived(), 0u, 59u);
246 
248  bounded2_p_t seconds_p (uint2_p.derived(), 0u, 59u);
249 
251  chset_t class_code_p ("A-Z");
252 
254  //
255  // (Boost Spirit) Grammar Definition
256  //
258 
259  // //////////////////////////////////////////////////////////////////////
261  OnDParser (stdair::BomRoot& ioBomRoot, OnDPeriodStruct& ioOnDPeriod)
262  : _bomRoot (ioBomRoot), _onDPeriod (ioOnDPeriod) {
263  }
264 
265  // //////////////////////////////////////////////////////////////////////
266  template<typename ScannerT>
268 
269  ond_list = *( boost::spirit::classic::comment_p("//")
270  | boost::spirit::classic::comment_p("/*", "*/")
271  | ond )
272  ;
273 
274  ond = ond_key
275  >> +( ';' >> segment )
276  >> ond_end[doEndOnD(self._bomRoot, self._onDPeriod)]
277  ;
278 
279  ond_end = boost::spirit::classic::ch_p(';')
280  ;
281 
282  ond_key = (airport_p)[storeOrigin(self._onDPeriod)]
283  >> ';' >> (airport_p)[storeDestination(self._onDPeriod)]
284  >> ';' >> date[storeDateRangeStart(self._onDPeriod)]
285  >> ';' >> date[storeDateRangeEnd(self._onDPeriod)]
286  >> ';' >> time[storeStartRangeTime(self._onDPeriod)]
287  >> ';' >> time[storeEndRangeTime(self._onDPeriod)]
288  ;
289 
290  date = boost::spirit::classic::
291  lexeme_d[(year_p)[boost::spirit::classic::
292  assign_a(self._onDPeriod._itYear)]
293  >> '-'
294  >> (month_p)[boost::spirit::classic::
295  assign_a(self._onDPeriod._itMonth)]
296  >> '-'
297  >> (day_p)[boost::spirit::classic::
298  assign_a(self._onDPeriod._itDay)]]
299  ;
300 
301  time = boost::spirit::classic::
302  lexeme_d[(hours_p)[boost::spirit::classic::
303  assign_a(self._onDPeriod._itHours)]
304  >> ':'
305  >> (minutes_p)[boost::spirit::classic::
306  assign_a(self._onDPeriod._itMinutes)]
307  >> !(':' >> (seconds_p)[boost::spirit::classic::
308  assign_a(self._onDPeriod._itSeconds)])]
309  ;
310 
311  segment = boost::spirit::classic::
312  lexeme_d[(airline_code_p)[storeAirlineCode(self._onDPeriod)]]
313  >> ';' >> (class_code_p)[storeClassCode(self._onDPeriod)]
314  ;
315 
316  //BOOST_SPIRIT_DEBUG_NODE (OnDParser);
317  BOOST_SPIRIT_DEBUG_NODE (ond_list);
318  BOOST_SPIRIT_DEBUG_NODE (ond);
319  BOOST_SPIRIT_DEBUG_NODE (segment);
320  BOOST_SPIRIT_DEBUG_NODE (ond_key);
321  BOOST_SPIRIT_DEBUG_NODE (ond_end);
322  BOOST_SPIRIT_DEBUG_NODE (date);
323  BOOST_SPIRIT_DEBUG_NODE (time);
324 
325  }
326 
327  // //////////////////////////////////////////////////////////////////////
328  template<typename ScannerT>
329  boost::spirit::classic::rule<ScannerT> const&
331  return ond_list;
332  }
333  }
334 
336  //
337  // Entry class for the file parser
338  //
340 
341  // //////////////////////////////////////////////////////////////////////
342  OnDPeriodFileParser::OnDPeriodFileParser (const stdair::Filename_T& iFilename,
343  stdair::BomRoot& ioBomRoot)
344  : _filename (iFilename), _bomRoot (ioBomRoot) {
345  init();
346  }
347 
348  // //////////////////////////////////////////////////////////////////////
349  void OnDPeriodFileParser::init() {
350  // Check that the file exists and is readable
351  const bool doesExistAndIsReadable =
352  stdair::BasFileMgr::doesExistAndIsReadable (_filename);
353 
354  if (doesExistAndIsReadable == false) {
355  STDAIR_LOG_ERROR ("The O&D file " << _filename
356  << " does not exist or can not be read.");
357 
358  throw OnDInputFileNotFoundException ("The O&D file " + _filename
359  + " does not exist or can not be read");
360  }
361 
362  // Open the file
363  _startIterator = iterator_t (_filename);
364 
365  // Check that the filename exists and can be open
366  if (!_startIterator) {
367  STDAIR_LOG_DEBUG ("The O&D file " << _filename << " can not be open."
368  << std::endl);
369  throw OnDInputFileNotFoundException ("The file " + _filename
370  + " does not exist or can not be read");
371  }
372 
373  // Create an EOF iterator
374  _endIterator = _startIterator.make_end();
375  }
376 
377  // //////////////////////////////////////////////////////////////////////
379  bool oResult = false;
380 
381  STDAIR_LOG_DEBUG ("Parsing O&D input file: " << _filename);
382 
383  // Initialise the parser (grammar) with the helper/staging structure.
384  OnDParserHelper::OnDParser lODParser (_bomRoot, _onDPeriod);
385 
386  // Launch the parsing of the file and, thanks to the doEndOnD
387  // call-back structure, filling the worldSchedule (Fares)
388  boost::spirit::classic::parse_info<iterator_t> info =
389  boost::spirit::classic::parse (_startIterator, _endIterator, lODParser,
390  boost::spirit::classic::space_p);
391 
392  // Retrieves whether or not the parsing was successful
393  oResult = info.hit;
394 
395  const std::string hasBeenFullyReadStr = (info.full == true)?"":"not ";
396  if (oResult == true) {
397  STDAIR_LOG_DEBUG ("Parsing of O&D input file: " << _filename
398  << " succeeded: read " << info.length
399  << " characters. The input file has "
400  << hasBeenFullyReadStr
401  << "been fully read. Stop point: " << info.stop);
402 
403  } else {
404  // TODO: decide whether to throw an exception
405  STDAIR_LOG_ERROR ("Parsing of O&D input file: " << _filename
406  << " failed: read " << info.length
407  << " characters. The input file has "
408  << hasBeenFullyReadStr
409  << "been fully read. Stop point: " << info.stop);
410  }
411 
412  return oResult;
413  }
414 }