OpenTREP Logo  0.07.11
C++ Open Travel Request Parsing Library
pyopentrep.cpp
Go to the documentation of this file.
1 // Python
2 #include <boost/python.hpp>
3 // STL
4 #include <cassert>
5 #include <stdexcept>
6 #include <fstream>
7 #include <sstream>
8 #include <string>
9 #include <list>
10 #include <vector>
11 // Boost Python
12 #include <boost/filesystem.hpp>
13 // OpenTREP
16 #include <opentrep/Location.hpp>
17 #include <opentrep/CityDetails.hpp>
20 
21 //
22 namespace bp = boost::python;
23 
24 namespace OPENTREP {
25 
31  public:
32 
40  std::string getPaths() {
41  return getPathsImpl();
42  }
43 
47  std::string index() {
48  return indexImpl();
49  }
50 
55  std::string generate (const std::string& iOutputFormatString,
56  const NbOfMatches_T& iNbOfDraws) {
57  const OutputFormat lOutputFormat (iOutputFormatString);
58  const OutputFormat::EN_OutputFormat& lOutputFormatEnum =
59  lOutputFormat.getFormat();
60  return generateImpl (iNbOfDraws, lOutputFormatEnum);
61  }
62 
67  bp::object generateToPB (const NbOfMatches_T& iNbOfDraws) {
68  const OutputFormat::EN_OutputFormat lOutputFormatEnum =
70  //
71  const std::string& oPBStr = generateImpl (iNbOfDraws, lOutputFormatEnum);
72 
73  const ssize_t lPBSize = oPBStr.size();
74 
75  // Convert to a byte array; otherwise Python considers it as a str
76  // (Unicode string in Python 3), and the decoding fails
77  const bp::object& oPBObj =
78  bp::object (bp::handle<> (PyBytes_FromStringAndSize (oPBStr.c_str(),
79  lPBSize)));
80 
81  return oPBObj;
82  }
83 
87  std::string search (const std::string& iOutputFormatString,
88  const std::string& iTravelQuery) {
89  const OutputFormat lOutputFormat (iOutputFormatString);
90  const OutputFormat::EN_OutputFormat& lOutputFormatEnum =
91  lOutputFormat.getFormat();
92  return searchImpl (iTravelQuery, lOutputFormatEnum);
93  }
94 
98  bp::object searchToPB (const std::string& iTravelQuery) {
99  const OutputFormat::EN_OutputFormat lOutputFormatEnum =
101  //
102  const std::string& oPBStr = searchImpl (iTravelQuery, lOutputFormatEnum);
103  const ssize_t lPBSize = oPBStr.size();
104 
105  // Convert to a byte array; otherwise Python considers it as a str
106  // (Unicode string in Python 3), and the decoding fails
107  const bp::object& oPBObj =
108  bp::object (bp::handle<> (PyBytes_FromStringAndSize (oPBStr.c_str(),
109  lPBSize)));
110 
111  return oPBObj;
112  }
113 
114  private:
118  std::string getPathsImpl() {
119  std::ostringstream oPythonLogStr;
120 
121  // Sanity check
122  if (_logOutputStream == NULL) {
123  oPythonLogStr << "The log filepath is not valid." << std::endl;
124  return oPythonLogStr.str();
125  }
126  assert (_logOutputStream != NULL);
127 
128  try {
129 
130  // DEBUG
131  *_logOutputStream << "Get the file-path details" << std::endl;
132 
133  if (_opentrepService == NULL) {
134  oPythonLogStr << "The OpenTREP service has not been initialized, "
135  << "i.e., the init() method has not been called "
136  << "correctly on the OpenTrepSearcher object. Please "
137  << "check that all the parameters are not empty and "
138  << "point to actual files.";
139  *_logOutputStream << oPythonLogStr.str();
140  return oPythonLogStr.str();
141  }
142  assert (_opentrepService != NULL);
143 
144  // Retrieve the underlying file-path details
145  const OPENTREP_Service::FilePathSet_T& lFilePathSet =
146  _opentrepService->getFilePaths();
147  const PORFilePath_T& lPORFilePath = lFilePathSet.first;
148  const OPENTREP_Service::DBFilePathPair_T& lDBFilePathPair =
149  lFilePathSet.second;
150  const TravelDBFilePath_T& lTravelDBFilePath = lDBFilePathPair.first;
151  const SQLDBConnectionString_T& lSQLDBConnStr = lDBFilePathPair.second;
152 
153  // Dump the results into the output string
154  oPythonLogStr << lPORFilePath << ";" << lTravelDBFilePath
155  << ";" << lSQLDBConnStr;
156 
157  // DEBUG
158  *_logOutputStream << "OPTD-maintained list of POR: '" << lPORFilePath
159  << "'" << std::endl;
160  *_logOutputStream << "Xapian travel database/index: '"
161  << lTravelDBFilePath << "'" << std::endl;
162  *_logOutputStream << "SQL database connection string: '"
163  << lSQLDBConnStr << "'" << std::endl;
164 
165  } catch (const RootException& eOpenTrepError) {
166  *_logOutputStream << "OpenTrep error: " << eOpenTrepError.what()
167  << std::endl;
168 
169  } catch (const std::exception& eStdError) {
170  *_logOutputStream << "Error: " << eStdError.what() << std::endl;
171 
172  } catch (...) {
173  *_logOutputStream << "Unknown error" << std::endl;
174  }
175 
176  //
177  return oPythonLogStr.str();
178  }
179 
183  std::string indexImpl() {
184  std::ostringstream oPythonLogStr;
185 
186  // Sanity check
187  if (_logOutputStream == NULL) {
188  oPythonLogStr << "The log filepath is not valid." << std::endl;
189  return oPythonLogStr.str();
190  }
191  assert (_logOutputStream != NULL);
192 
193  try {
194 
195  // DEBUG
196  *_logOutputStream << "Indexation by Xapian" << std::endl;
197 
198  if (_opentrepService == NULL) {
199  oPythonLogStr << "The OpenTREP service has not been initialized, "
200  << "i.e., the init() method has not been called "
201  << "correctly on the OpenTrepSearcher object. Please "
202  << "check that all the parameters are not empty and "
203  << "point to actual files.";
204  *_logOutputStream << oPythonLogStr.str();
205  return oPythonLogStr.str();
206  }
207  assert (_opentrepService != NULL);
208 
209  // Retrieve the underlying file-path details
210  const OPENTREP_Service::FilePathSet_T& lFilePathSet =
211  _opentrepService->getFilePaths();
212  const PORFilePath_T& lPORFilePath = lFilePathSet.first;
213  const OPENTREP_Service::DBFilePathPair_T& lDBFilePathPair =
214  lFilePathSet.second;
215  const TravelDBFilePath_T& lTravelDBFilePath = lDBFilePathPair.first;
216  const SQLDBConnectionString_T& lSQLDBConnStr = lDBFilePathPair.second;
217 
218  // DEBUG
219  *_logOutputStream << "OPTD-maintained list of POR: '" << lPORFilePath
220  << "'" << std::endl;
221  *_logOutputStream << "Xapian travel database/index: '"
222  << lTravelDBFilePath << "'" << std::endl;
223  *_logOutputStream << "SQL database connection string: '"
224  << lSQLDBConnStr << "'" << std::endl;
225 
226  // Launch the indexation by Xapian of the OPTD-maintained list of POR
227  const NbOfDBEntries_T lNbOfEntries= _opentrepService->insertIntoDBAndXapian();
228 
229  // Dump the results into the output string
230  oPythonLogStr << lNbOfEntries;
231 
232  // DEBUG
233  *_logOutputStream << "Xapian indexation yielded " << lNbOfEntries
234  << " POR (points of reference) entries." << std::endl;
235 
236  } catch (const RootException& eOpenTrepError) {
237  *_logOutputStream << "OpenTrep error: " << eOpenTrepError.what()
238  << std::endl;
239 
240  } catch (const std::exception& eStdError) {
241  *_logOutputStream << "Error: " << eStdError.what() << std::endl;
242 
243  } catch (...) {
244  *_logOutputStream << "Unknown error" << std::endl;
245  }
246 
247  //
248  return oPythonLogStr.str();
249  }
250 
254  std::string searchImpl (const std::string& iTravelQuery,
255  const OutputFormat::EN_OutputFormat& iOutputFormat) {
256  const std::string oEmptyStr ("");
257  std::ostringstream oNoDetailedStr;
258  std::ostringstream oDetailedStr;
259  std::ostringstream oJSONStr;
260  std::ostringstream oProtobufStr;
261 
262  // Sanity check
263  if (_logOutputStream == NULL) {
264  oNoDetailedStr << "The log filepath is not valid." << std::endl;
265  return oNoDetailedStr.str();
266  }
267  assert (_logOutputStream != NULL);
268 
269  try {
270 
271  // DEBUG
272  *_logOutputStream << "Travel query ('" << iTravelQuery << "'"
273  << "') search" << std::endl;
274 
275  if (_opentrepService == NULL) {
276  oNoDetailedStr << "The OpenTREP service has not been initialized, "
277  << "i.e., the init() method has not been called "
278  << "correctly on the OpenTrepSearcher object. Please "
279  << "check that all the parameters are not empty and "
280  << "point to actual files.";
281  *_logOutputStream << oNoDetailedStr.str();
282  return oNoDetailedStr.str();
283  }
284  assert (_opentrepService != NULL);
285 
286  // Retrieve the underlying file-path details
287  const OPENTREP_Service::FilePathSet_T& lFilePathSet =
288  _opentrepService->getFilePaths();
289  const PORFilePath_T& lPORFilePath = lFilePathSet.first;
290  const OPENTREP_Service::DBFilePathPair_T& lDBFilePathPair =
291  lFilePathSet.second;
292  const TravelDBFilePath_T& lTravelDBFilePath = lDBFilePathPair.first;
293  const SQLDBConnectionString_T& lSQLDBConnStr = lDBFilePathPair.second;
294 
295  // Check the directory of the Xapian database/index exists
296  // and is accessible
297  const OPENTREP::DeploymentNumber_T& lDeploymentNumber =
298  _opentrepService->getDeploymentNumber();
299  const bool lExistXapianDBDir =
300  _opentrepService->checkXapianDBOnFileSystem (lTravelDBFilePath);
301  if (lExistXapianDBDir == false) {
302  *_logOutputStream << "Error - The file-path to the Xapian "
303  << "database/index ('" << lTravelDBFilePath
304  << "') does not exist or is not a directory."
305  << std::endl;
306  *_logOutputStream << "Error - That usually means that the OpenTREP "
307  << "indexer (opentrep-indexer) has not been "
308  << "launched yet, or that it has operated on a "
309  << "different Xapian database/index file-path."
310  << std::endl;
311  *_logOutputStream << "Error - For instance the Xapian database/index "
312  << "may have been created with a different "
313  << "deployment number (" << lDeploymentNumber
314  << " being the current deployment number)";
315  return oNoDetailedStr.str();
316  }
317 
318  // DEBUG
319  *_logOutputStream << "Xapian travel database/index: '"
320  << lTravelDBFilePath
321  << "' - SQL database connection string: '"
322  << lSQLDBConnStr
323  << "' - OPTD-maintained list of POR: '"
324  << lPORFilePath << "'" << std::endl;
325 
326  // Query the Xapian database (index)
327  WordList_T lNonMatchedWordList;
328  LocationList_T lLocationList;
329  const NbOfMatches_T nbOfMatches =
330  _opentrepService->interpretTravelRequest (iTravelQuery, lLocationList,
331  lNonMatchedWordList);
332 
333  // DEBUG
334  *_logOutputStream << "Python search for '" << iTravelQuery << "' gave "
335  << nbOfMatches << " matches." << std::endl;
336 
337  if (nbOfMatches != 0) {
338  NbOfMatches_T idx = 0;
339 
340  for(LocationList_T::const_iterator itLocation = lLocationList.begin();
341  itLocation != lLocationList.end(); ++itLocation, ++idx) {
342  const Location& lLocation = *itLocation;
343 
344  if (idx != 0) {
345  oNoDetailedStr << ",";
346  }
347 
348  //
349  oNoDetailedStr << lLocation.getIataCode();
350  oDetailedStr << idx+1 << ". " << lLocation.toSingleLocationString()
351  << std::endl;
352 
353  // List of extra matching locations (those with the same
354  // matching weight/percentage)
355  const LocationList_T& lExtraLocationList =
356  lLocation.getExtraLocationList();
357  if (lExtraLocationList.empty() == false) {
358  oDetailedStr << " Extra matches: " << std::endl;
359 
360  NbOfMatches_T idxExtra = 0;
361  for (LocationList_T::const_iterator itLoc =
362  lExtraLocationList.begin();
363  itLoc != lExtraLocationList.end(); ++itLoc, ++idxExtra) {
364  oNoDetailedStr << ":";
365  oDetailedStr << " " << idx+1 << "." << idxExtra+1 << ". ";
366 
367  const Location& lExtraLocation = *itLoc;
368  oNoDetailedStr << lExtraLocation.getIataCode();
369  oDetailedStr << lExtraLocation << std::endl;
370  }
371  }
372 
373  // The matching weight/percentage is the same for the main
374  // and the extra matching locations
375  oNoDetailedStr << "/" << lLocation.getPercentage();
376 
377  // List of alternate matching locations (those with a lower
378  // matching weight/percentage)
379  const LocationList_T& lAlternateLocationList =
380  lLocation.getAlternateLocationList();
381  if (lAlternateLocationList.empty() == false) {
382  oDetailedStr << " Alternate matches: " << std::endl;
383 
384  NbOfMatches_T idxAlter = 0;
385  for (LocationList_T::const_iterator itLoc =
386  lAlternateLocationList.begin();
387  itLoc != lAlternateLocationList.end(); ++itLoc, ++idxAlter) {
388  oNoDetailedStr << "-";
389  oDetailedStr << " " << idx+1 << "." << idxAlter+1 << ". ";
390 
391  const Location& lAlternateLocation = *itLoc;
392  oNoDetailedStr << lAlternateLocation.getIataCode()
393  << "/" << lAlternateLocation.getPercentage();
394  oDetailedStr << lAlternateLocation << std::endl;
395  }
396  }
397  }
398  }
399 
400  if (lNonMatchedWordList.empty() == false) {
401  oNoDetailedStr << ";";
402  oDetailedStr << "Not recognised words:" << std::endl;
403  NbOfMatches_T idx = 0;
404  for (WordList_T::const_iterator itWord = lNonMatchedWordList.begin();
405  itWord != lNonMatchedWordList.end(); ++itWord, ++idx) {
406  const Word_T& lWord = *itWord;
407  if (idx != 0) {
408  oNoDetailedStr << ",";
409  oDetailedStr << idx+1 << "." << std::endl;
410  }
411  oNoDetailedStr << lWord;
412  oDetailedStr << lWord;
413  }
414  }
415 
416  // DEBUG
417  *_logOutputStream << "Python search for '" << iTravelQuery
418  << "' yielded:" << std::endl;
419 
420  // Export the list of Location objects into a JSON-formatted string
421  BomJSONExport::jsonExportLocationList (oJSONStr, lLocationList);
422 
423  // Export the list of Location objects into a Protobuf-formatted string
424  oProtobufStr << LocationExchange::exportLocationList(lLocationList,
425  lNonMatchedWordList)
426  << std::flush;
427 
428  } catch (const RootException& eOpenTrepError) {
429  *_logOutputStream << "OpenTrep error: " << eOpenTrepError.what()
430  << std::endl;
431 
432  } catch (const std::exception& eStdError) {
433  *_logOutputStream << "Error: " << eStdError.what() << std::endl;
434 
435  } catch (...) {
436  *_logOutputStream << "Unknown error" << std::endl;
437  }
438 
439  // Return the string corresponding to the request (either with
440  // or without details).
441  switch (iOutputFormat) {
442  case OutputFormat::SHORT: {
443  // DEBUG
444  const std::string& oNoDetailedString = oNoDetailedStr.str();
445  *_logOutputStream << "Short version ("
446  << oNoDetailedString.size() << " char): "
447  << oNoDetailedString << std::endl;
448  return oNoDetailedString;
449  }
450 
451  case OutputFormat::FULL: {
452  // DEBUG
453  const std::string& oDetailedString = oDetailedStr.str();
454  *_logOutputStream << "Long version ("
455  << oDetailedString.size() << " char): "
456  << oDetailedString << std::endl;
457  return oDetailedString;
458  }
459 
460  case OutputFormat::JSON: {
461  // DEBUG
462  const std::string& oJSONString = oJSONStr.str();
463  *_logOutputStream << "JSON version ("
464  << oJSONString.size() << " char): "
465  << oJSONString << std::endl;
466  return oJSONString;
467  }
468 
469  case OutputFormat::PROTOBUF: {
470  // DEBUG
471  const std::string& oProtobufString = oProtobufStr.str();
472  *_logOutputStream << "Protobuf version ("
473  << oProtobufString.size() << " char): "
474  << oProtobufString << std::endl;
475  return oProtobufString;
476  }
477 
478  default: {
479  // If the output format is not known, an exception is thrown by
480  // the call to the OutputFormat() constructor above.
481  assert (false);
482  }
483  }
484 
485  // That line cannot be reached, but some compilers fail if no final return
486  return oEmptyStr;
487  }
488 
492  std::string generateImpl(const NbOfMatches_T& iNbOfDraws,
493  const OutputFormat::EN_OutputFormat& iOutputFormat){
494  const std::string oEmptyStr ("");
495  std::ostringstream oNoDetailedStr;
496  std::ostringstream oDetailedStr;
497  std::ostringstream oJSONStr;
498  std::ostringstream oProtobufStr;
499 
500  // Sanity check
501  if (_logOutputStream == NULL) {
502  oNoDetailedStr << "The log filepath is not valid." << std::endl;
503  return oNoDetailedStr.str();
504  }
505  assert (_logOutputStream != NULL);
506 
507  try {
508 
509  // DEBUG
510  *_logOutputStream << "Number of random draws: " << iNbOfDraws
511  << std::endl;
512 
513  if (_opentrepService == NULL) {
514  oNoDetailedStr << "The OpenTREP service has not been initialized, "
515  << "i.e., the init() method has not been called "
516  << "correctly on the OpenTrepSearcher object. Please "
517  << "check that all the parameters are not empty and "
518  << "point to actual files.";
519  *_logOutputStream << oNoDetailedStr.str();
520  return oNoDetailedStr.str();
521  }
522  assert (_opentrepService != NULL);
523 
524  // Retrieve the underlying file-path details
525  const OPENTREP_Service::FilePathSet_T& lFilePathSet =
526  _opentrepService->getFilePaths();
527  const PORFilePath_T& lPORFilePath = lFilePathSet.first;
528  const OPENTREP_Service::DBFilePathPair_T& lDBFilePathPair =
529  lFilePathSet.second;
530  const TravelDBFilePath_T& lTravelDBFilePath = lDBFilePathPair.first;
531  const SQLDBConnectionString_T& lSQLDBConnStr = lDBFilePathPair.second;
532 
533  // DEBUG
534  *_logOutputStream << "Xapian travel database/index: '"
535  << lTravelDBFilePath
536  << "' - SQL database connection string: '"
537  << lSQLDBConnStr
538  << "' - OPTD-maintained list of POR: '"
539  << lPORFilePath << "'" << std::endl;
540 
541  // Query the Xapian database (index)
542  LocationList_T lLocationList;
543  const NbOfMatches_T nbOfMatches =
544  _opentrepService->drawRandomLocations (iNbOfDraws, lLocationList);
545 
546  // DEBUG
547  *_logOutputStream << "Python generation of " << iNbOfDraws << " gave "
548  << nbOfMatches << " documents." << std::endl;
549 
550  if (nbOfMatches != 0) {
551  NbOfMatches_T idx = 0;
552 
553  for(LocationList_T::const_iterator itLocation = lLocationList.begin();
554  itLocation != lLocationList.end(); ++itLocation, ++idx) {
555  const Location& lLocation = *itLocation;
556 
557  if (idx != 0) {
558  oNoDetailedStr << ",";
559  }
560 
561  //
562  oNoDetailedStr << lLocation.getIataCode();
563  oDetailedStr << idx+1 << ". " << lLocation.toSingleLocationString()
564  << std::endl;
565 
566  // List of extra matching locations (those with the same
567  // matching weight/percentage)
568  const LocationList_T& lExtraLocationList =
569  lLocation.getExtraLocationList();
570  if (lExtraLocationList.empty() == false) {
571  oDetailedStr << " Extra matches: " << std::endl;
572 
573  NbOfMatches_T idxExtra = 0;
574  for (LocationList_T::const_iterator itLoc =
575  lExtraLocationList.begin();
576  itLoc != lExtraLocationList.end(); ++itLoc, ++idxExtra) {
577  oNoDetailedStr << ":";
578  oDetailedStr << " " << idx+1 << "." << idxExtra+1 << ". ";
579 
580  const Location& lExtraLocation = *itLoc;
581  oNoDetailedStr << lExtraLocation.getIataCode();
582  oDetailedStr << lExtraLocation << std::endl;
583  }
584  }
585 
586  // The matching weight/percentage is the same for the main
587  // and the extra matching locations
588  oNoDetailedStr << "/" << lLocation.getPercentage();
589 
590  // List of alternate matching locations (those with a lower
591  // matching weight/percentage)
592  const LocationList_T& lAlternateLocationList =
593  lLocation.getAlternateLocationList();
594  if (lAlternateLocationList.empty() == false) {
595  oDetailedStr << " Alternate matches: " << std::endl;
596 
597  NbOfMatches_T idxAlter = 0;
598  for (LocationList_T::const_iterator itLoc =
599  lAlternateLocationList.begin();
600  itLoc != lAlternateLocationList.end(); ++itLoc, ++idxAlter) {
601  oNoDetailedStr << "-";
602  oDetailedStr << " " << idx+1 << "." << idxAlter+1 << ". ";
603 
604  const Location& lAlternateLocation = *itLoc;
605  oNoDetailedStr << lAlternateLocation.getIataCode()
606  << "/" << lAlternateLocation.getPercentage();
607  oDetailedStr << lAlternateLocation << std::endl;
608  }
609  }
610  }
611  }
612 
613  // DEBUG
614  *_logOutputStream << "Python generation of " << iNbOfDraws
615  << " yielded:" << std::endl;
616 
617  // Export the list of Location objects into a JSON-formatted string
618  BomJSONExport::jsonExportLocationList (oJSONStr, lLocationList);
619 
620  // Export the list of Location objects into a Protobuf-formatted string
621  WordList_T lNonMatchedWordList;
622  oProtobufStr << LocationExchange::exportLocationList(lLocationList,
623  lNonMatchedWordList)
624  << std::flush;
625 
626  } catch (const RootException& eOpenTrepError) {
627  *_logOutputStream << "OpenTrep error: " << eOpenTrepError.what()
628  << std::endl;
629 
630  } catch (const std::exception& eStdError) {
631  *_logOutputStream << "Error: " << eStdError.what() << std::endl;
632 
633  } catch (...) {
634  *_logOutputStream << "Unknown error" << std::endl;
635  }
636 
637  // Return the string corresponding to the request (either with
638  // or without details).
639  switch (iOutputFormat) {
640  case OutputFormat::SHORT: {
641  // DEBUG
642  const std::string& oNoDetailedString = oNoDetailedStr.str();
643  *_logOutputStream << "Short version ("
644  << oNoDetailedString.size() << " char): "
645  << oNoDetailedString << std::endl;
646  return oNoDetailedString;
647  }
648 
649  case OutputFormat::FULL: {
650  // DEBUG
651  const std::string& oDetailedString = oDetailedStr.str();
652  *_logOutputStream << "Long version ("
653  << oDetailedString.size() << " char): "
654  << oDetailedString << std::endl;
655  return oDetailedString;
656  }
657 
658  case OutputFormat::JSON: {
659  // DEBUG
660  const std::string& oJSONString = oJSONStr.str();
661  *_logOutputStream << "JSON version ("
662  << oJSONString.size() << " char): "
663  << oJSONString << std::endl;
664  return oJSONString;
665  }
666 
667  case OutputFormat::PROTOBUF: {
668  // DEBUG
669  const std::string& oProtobufString = oProtobufStr.str();
670  *_logOutputStream << "Protobuf version ("
671  << oProtobufString.size() << " char): "
672  << oProtobufString << std::endl;
673  return oProtobufString;
674  }
675 
676  default: {
677  // If the output format is not known, an exception is thrown by
678  // the call to the OutputFormat() constructor above.
679  assert (false);
680  }
681  }
682 
683  // That line cannot be reached, but some compilers fail if no final return
684  return oEmptyStr;
685  }
686 
687  public:
691  OpenTrepSearcher() : _opentrepService (NULL), _logOutputStream (NULL) {
692  }
693 
697  OpenTrepSearcher (const OpenTrepSearcher& iOpenTrepSearcher)
698  : _opentrepService (iOpenTrepSearcher._opentrepService),
699  _logOutputStream (iOpenTrepSearcher._logOutputStream) {
700  }
701 
706  _opentrepService = NULL;
707  _logOutputStream = NULL;
708  }
709 
715  bool init (const std::string& iPORFilePath,
716  const std::string& iTravelDBFilePath,
717  const std::string& iSQLDBTypeStr,
718  const std::string& iSQLDBConnStr,
719  const unsigned short& iDeploymentNumber,
720  const bool iDontIndexIATAPOR,
721  const bool iIndexPORInXapian,
722  const bool iAddPORInDB,
723  const std::string& iLogFilePath) {
724  bool isEverythingOK = true;
725 
726  try {
727 
728  // Add the deployment number/version to the Xapian file-path
729  std::ostringstream oXFP;
730  oXFP << iTravelDBFilePath << iDeploymentNumber;
731  const std::string lXapianFP = oXFP.str();
732 
733  // Set the log parameters
734  _logOutputStream = new std::ofstream;
735  assert (_logOutputStream != NULL);
736 
737  // Open and clean the log outputfile
738  _logOutputStream->open (iLogFilePath.c_str());
739  _logOutputStream->clear();
740 
741  // DEBUG
742  *_logOutputStream << "[pyopentrep][init] Python wrapper initialization"
743  << std::endl;
744 
745  // Initialize the context
746  const OPENTREP::TravelDBFilePath_T lTravelDBFilePath (iTravelDBFilePath);
747  const OPENTREP::PORFilePath_T lPORFilePath (iPORFilePath);
748  const OPENTREP::DBType lSQLDBType (iSQLDBTypeStr);
749  const OPENTREP::SQLDBConnectionString_T lSQLDBConnStr (iSQLDBConnStr);
750  const OPENTREP::DeploymentNumber_T lDeploymentNumber (iDeploymentNumber);
752  lDontIndexIATAPOR (iDontIndexIATAPOR);
754  lIndexPORInXapian (iIndexPORInXapian);
755  const OPENTREP::shouldAddPORInSQLDB_T lAddPORInDB (iAddPORInDB);
756 
757  _opentrepService = new OPENTREP_Service (*_logOutputStream,
758  lPORFilePath,
759  lTravelDBFilePath,
760  lSQLDBType, lSQLDBConnStr,
761  lDeploymentNumber,
762  lDontIndexIATAPOR,
763  lIndexPORInXapian,
764  lAddPORInDB);
765 
766  // DEBUG
767  *_logOutputStream << "[pyopentrep][init] Python wrapper initialized."
768  << " Parameters:" << std::endl;
769  *_logOutputStream << "[pyopentrep][init] POR data file: "
770  << iPORFilePath << std::endl;
771  *_logOutputStream << "[pyopentrep][init] Xapian DB: "
772  << iTravelDBFilePath << std::endl;
773  *_logOutputStream << "[pyopentrep][init][DB] Type: " << iSQLDBTypeStr
774  << " - Connection string: " << iSQLDBConnStr
775  << std::endl;
776  *_logOutputStream << "[pyopentrep][init] Deployment number: "
777  << iDeploymentNumber << std::endl;
778  *_logOutputStream << "[pyopentrep][init] Should index non-IATA POR? "
779  << iDontIndexIATAPOR << std::endl;
780  *_logOutputStream << "[pyopentrep][init] Should index POR in Xapian? "
781  << iIndexPORInXapian << std::endl;
782  *_logOutputStream << "[pyopentrep][init] Should add POR in database? "
783  << iAddPORInDB << std::endl;
784 
785  } catch (const RootException& eOpenTrepError) {
786  *_logOutputStream << "OpenTrep error: " << eOpenTrepError.what()
787  << std::endl;
788 
789  } catch (const std::exception& eStdError) {
790  *_logOutputStream << "Error: " << eStdError.what() << std::endl;
791 
792  } catch (...) {
793  *_logOutputStream << "Unknown error" << std::endl;
794  }
795 
796  return isEverythingOK;
797  }
798 
802  bool finalize () {
803  bool isEverythingOK = true;
804 
805  try {
806 
807  // Finalize the context
808  if (_opentrepService != NULL) {
809  delete _opentrepService; _opentrepService = NULL;
810  }
811 
812  // Close the output stream
813  if (_logOutputStream != NULL) {
814  // DEBUG
815  *_logOutputStream << "Python wrapper finalization" << std::endl;
816  _logOutputStream->close();
817  delete _logOutputStream; _logOutputStream = NULL;
818  }
819 
820  } catch (...) {
821  }
822 
823  return isEverythingOK;
824  }
825 
826  private:
830  OPENTREP_Service* _opentrepService;
831  std::ofstream* _logOutputStream;
832  };
833 
834 }
835 
836 // /////////////////////////////////////////////////////////////
837 BOOST_PYTHON_MODULE(pyopentrep) {
838  boost::python::class_<OPENTREP::OpenTrepSearcher> ("OpenTrepSearcher")
839  .def ("index", &OPENTREP::OpenTrepSearcher::index)
840  .def ("search", &OPENTREP::OpenTrepSearcher::search)
841  .def ("searchToPB", &OPENTREP::OpenTrepSearcher::searchToPB)
842  .def ("generate", &OPENTREP::OpenTrepSearcher::generate)
843  .def ("generateToPB", &OPENTREP::OpenTrepSearcher::generateToPB)
844  .def ("getPaths", &OPENTREP::OpenTrepSearcher::getPaths)
845  .def ("init", &OPENTREP::OpenTrepSearcher::init)
846  .def ("finalize", &OPENTREP::OpenTrepSearcher::finalize);
847 }
bp::object generateToPB(const NbOfMatches_T &iNbOfDraws)
Definition: pyopentrep.cpp:67
unsigned short NbOfMatches_T
const char * what() const
FilePathSet_T getFilePaths() const
static std::string exportLocationList(const LocationList_T &, const WordList_T &iNonMatchedWordList)
std::string Word_T
bool shouldIndexNonIATAPOR_T
OpenTrepSearcher(const OpenTrepSearcher &iOpenTrepSearcher)
Definition: pyopentrep.cpp:697
NbOfDBEntries_T insertIntoDBAndXapian()
unsigned int NbOfDBEntries_T
Interface for the OPENTREP Services.
std::vector< std::string > WordList_T
NbOfMatches_T drawRandomLocations(const NbOfMatches_T &iNbOfDraws, LocationList_T &)
Enumeration of database types.
Definition: DBType.hpp:17
Root of the OpenTREP exceptions.
Enumeration of output formats.
std::string search(const std::string &iOutputFormatString, const std::string &iTravelQuery)
Definition: pyopentrep.cpp:87
bool init(const std::string &iPORFilePath, const std::string &iTravelDBFilePath, const std::string &iSQLDBTypeStr, const std::string &iSQLDBConnStr, const unsigned short &iDeploymentNumber, const bool iDontIndexIATAPOR, const bool iIndexPORInXapian, const bool iAddPORInDB, const std::string &iLogFilePath)
Definition: pyopentrep.cpp:715
bool checkXapianDBOnFileSystem(const TravelDBFilePath_T &) const
API wrapper around the OpenTREP C++ API, so that Python scripts can use it seamlessly.
Definition: pyopentrep.cpp:30
std::list< Location > LocationList_T
NbOfMatches_T interpretTravelRequest(const std::string &iTravelQuery, LocationList_T &, WordList_T &)
bool shouldAddPORInSQLDB_T
bool shouldIndexPORInXapian_T
std::pair< const PORFilePath_T, const DBFilePathPair_T > FilePathSet_T
static EN_OutputFormat getFormat(const char)
BOOST_PYTHON_MODULE(pyopentrep)
Definition: pyopentrep.cpp:837
const DeploymentNumber_T & getDeploymentNumber() const
static void jsonExportLocationList(std::ostream &, const LocationList_T &)
bp::object searchToPB(const std::string &iTravelQuery)
Definition: pyopentrep.cpp:98
std::string generate(const std::string &iOutputFormatString, const NbOfMatches_T &iNbOfDraws)
Definition: pyopentrep.cpp:55
unsigned short DeploymentNumber_T
std::pair< const TravelDBFilePath_T, const SQLDBConnectionString_T > DBFilePathPair_T