SimFQT Logo  0.1.2
C++ Simulated Fare Quote System Library
FareQuoter.cpp
Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 #include <sstream>
00007 // StdAir
00008 #include <stdair/basic/BasParserTypes.hpp>
00009 #include <stdair/basic/BasConst_BomDisplay.hpp>
00010 #include <stdair/bom/BomKeyManager.hpp>
00011 #include <stdair/bom/ParsedKey.hpp>
00012 #include <stdair/bom/BomManager.hpp>
00013 #include <stdair/bom/BomRoot.hpp>
00014 #include <stdair/bom/InventoryKey.hpp>
00015 #include <stdair/bom/FlightDateKey.hpp>
00016 #include <stdair/bom/SegmentDateKey.hpp>
00017 #include <stdair/bom/AirlineClassList.hpp>
00018 #include <stdair/bom/AirportPair.hpp>
00019 #include <stdair/bom/PosChannel.hpp>
00020 #include <stdair/bom/DatePeriod.hpp>
00021 #include <stdair/bom/TimePeriod.hpp>
00022 #include <stdair/bom/FareFeatures.hpp>
00023 #include <stdair/bom/BookingRequestStruct.hpp>
00024 #include <stdair/bom/TravelSolutionStruct.hpp>
00025 #include <stdair/service/Logger.hpp>
00026 #include <stdair/bom/key_types.hpp>
00027 // SimFQT
00028 #include <simfqt/SIMFQT_Types.hpp>
00029 #include <simfqt/command/FareQuoter.hpp>
00030 
00031 namespace SIMFQT {
00032 
00033   bool FareQuoter::_atLeastOneAvailableDateRule = false;
00034   bool FareQuoter::_atLeastOneAvailablePosChannel = false;
00035   bool FareQuoter::_atLeastOneAvailableTimeRule = false;
00036   bool FareQuoter::_atLeastOneAvailableFeaturesRule = false;
00037   bool FareQuoter::_atLeastOneAvailableAirlineClassRule= false;
00038 
00039   // //////////////////////////////////////////////////////////////////////
00040   FareQuoter::FareQuoter() {
00041     assert (false);
00042   }
00043 
00044   // //////////////////////////////////////////////////////////////////////
00045   FareQuoter::FareQuoter(const FareQuoter&) {
00046     assert (false);
00047   }
00048 
00049   // //////////////////////////////////////////////////////////////////////
00050   FareQuoter::~FareQuoter() {
00051   }
00052   
00053   // //////////////////////////////////////////////////////////////////////
00054   void FareQuoter::reset() {
00055     _atLeastOneAvailableDateRule = false;
00056     _atLeastOneAvailablePosChannel = false;
00057     _atLeastOneAvailableTimeRule = false;
00058     _atLeastOneAvailableFeaturesRule = false;
00059     _atLeastOneAvailableAirlineClassRule = false;
00060   }
00061 
00062 
00063   // //////////////////////////////////////////////////////////////////////
00064   void FareQuoter::
00065   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00066               stdair::TravelSolutionList_T& ioTravelSolutionList,
00067               const stdair::BomRoot& iBomRoot) {
00068 
00069     // Do an independent price quote for each travel solution related to the
00070     // booking request.
00071     for (stdair::TravelSolutionList_T::iterator itTravelSolution =
00072            ioTravelSolutionList.begin();
00073          itTravelSolution != ioTravelSolutionList.end(); ++itTravelSolution) {
00074       reset();
00075       // Select a travel solution.
00076       stdair::TravelSolutionStruct& lTravelSolutionStruct = *itTravelSolution;
00077       // Price quote the travel solution into question.
00078       priceQuote (iBookingRequest, lTravelSolutionStruct, iBomRoot);
00079     }
00080   }
00081 
00082   // //////////////////////////////////////////////////////////////////////
00083   void FareQuoter::
00084   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00085               stdair::TravelSolutionStruct& ioTravelSolution,
00086               const stdair::BomRoot& iBomRoot) {
00087 
00088     // Get the origin of the first segment in order to get the origin of
00089     // the solution.
00090     const stdair::ParsedKey& lFirstSegmentKey =
00091       getFirstSPParsedKey(ioTravelSolution);
00092     const stdair::AirportCode_T& lOrigin = lFirstSegmentKey._boardingPoint;
00093 
00094     // Get the destination of the last segment in order to get the
00095     // destination of the solution.
00096     const stdair::ParsedKey& lLastSegmentKey =
00097       getLastSPParsedKey(ioTravelSolution);
00098     const stdair::AirportCode_T& lDestination = lLastSegmentKey._offPoint;
00099 
00100     // Construct the Airport pair stream of the segment path.
00101     const stdair::AirportPairKey lAirportPairKey (lOrigin, lDestination);
00102     
00103     // Search for the fare rules having the same origin and destination airports
00104     // as the travel solution
00105     const stdair::AirportPair* lAirportPair_ptr = stdair::BomManager::
00106       getObjectPtr<stdair::AirportPair> (iBomRoot, lAirportPairKey.toString());  
00107 
00108     // If no fare rule has the same origin and destination airports, the pricing
00109     // is not possible, throw an exception.
00110     if (lAirportPair_ptr == NULL) { 
00111       STDAIR_LOG_ERROR ("No available fare rule for the "
00112                         << "Origin-Destination pair: "
00113                         << lAirportPairKey.toString());
00114       throw AirportPairNotFoundException ("No available fare rule for "
00115                                           "the Origin-Destination pair: "
00116                                           + lAirportPairKey.toString());
00117     }
00118     // Sanity check.
00119     assert(lAirportPair_ptr != NULL);
00120 
00121     // Fare rule(s) with the same origin and destination airports exist(s), now
00122     // the date range need to be checked.
00123     const stdair::AirportPair& lAirportPair = *lAirportPair_ptr;
00124     priceQuote(iBookingRequest, ioTravelSolution, lAirportPair);
00125 
00126     if (_atLeastOneAvailableAirlineClassRule == false) {
00127       displayMissingFareRuleMessage(iBookingRequest, ioTravelSolution);
00128     }
00129   }
00130 
00131   // //////////////////////////////////////////////////////////////////////
00132   void FareQuoter::
00133   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00134               stdair::TravelSolutionStruct& ioTravelSolution,
00135               const stdair::AirportPair& iAirportPair) {
00136 
00137     // Get the first segment path parsed key.
00138     const stdair::ParsedKey lFirstSPParsedKey =
00139       getFirstSPParsedKey(ioTravelSolution);
00140 
00141     // Get the date of the first segment date key.
00142     const stdair::FlightDateKey& lFlightDateKey =
00143       lFirstSPParsedKey.getFlightDateKey();
00144     const stdair::Date_T& lSPDate = lFlightDateKey.getDepartureDate();
00145 
00146     // Get the list of the fare date ranges.
00147     const stdair::DatePeriodList_T& lFareDatePeriodList =
00148       stdair::BomManager::getList<stdair::DatePeriod> (iAirportPair);
00149 
00150     // Browse the list of the fare rules date range.
00151     for (stdair::DatePeriodList_T::const_iterator itDateRange =
00152            lFareDatePeriodList.begin();
00153          itDateRange != lFareDatePeriodList.end(); ++itDateRange) {
00154 
00155       const stdair::DatePeriod* lCurrentFareDatePeriod_ptr = *itDateRange ;
00156       assert (lCurrentFareDatePeriod_ptr != NULL);
00157 
00158       // Select the fare rules having a corresponding date range.
00159       const bool isDepartureDateValid =
00160         lCurrentFareDatePeriod_ptr->isDepartureDateValid (lSPDate);
00161 
00162       // If a fare rule has a corresponding date range, its channel and position
00163       // need to be checked.
00164       if (isDepartureDateValid == true) {
00165         _atLeastOneAvailableDateRule = true;
00166         const stdair::DatePeriod& lCurrentFareDatePeriod =
00167           *lCurrentFareDatePeriod_ptr;
00168         priceQuote (iBookingRequest, ioTravelSolution,
00169                     lCurrentFareDatePeriod, iAirportPair);
00170       }
00171     }
00172     
00173   }
00174 
00175   // //////////////////////////////////////////////////////////////////////
00176   void FareQuoter::
00177   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00178               stdair::TravelSolutionStruct& ioTravelSolution,
00179               const stdair::DatePeriod& iFareDatePeriod,
00180               const stdair::AirportPair& iAirportPair) {
00181 
00182     // Get the point-of-sale of the booking request.
00183     const stdair::CityCode_T& lPointOfSale = iBookingRequest.getPOS();
00184 
00185     // Get the booking request channel.
00186     const stdair::ChannelLabel_T& lChannel =
00187       iBookingRequest.getBookingChannel();
00188 
00189     // Construct the corresponding POS-channel primary key.
00190     const stdair::PosChannelKey lFarePosChannelKey (lPointOfSale, lChannel);
00191 
00192     // Search for the fare rules having the same point-of-sale and channel as
00193     // the travel solution.
00194     const stdair::PosChannelList_T lFarePosChannelList =
00195       stdair::BomManager::getList<stdair::PosChannel> (iFareDatePeriod);
00196 
00197     // Browse the list of the fare rules pos channel.
00198     for (stdair::PosChannelList_T::const_iterator itPosChannel =
00199            lFarePosChannelList.begin();
00200          itPosChannel != lFarePosChannelList.end();
00201          ++itPosChannel) {
00202       const stdair::PosChannel* lCurrentFarePosChannel_ptr = *itPosChannel;
00203       assert (lCurrentFarePosChannel_ptr != NULL);
00204 
00205       // Get the point-of-sale and channel of the current fare rule.
00206       const stdair::CityCode_T& lCurrentPointOfSale =
00207         lCurrentFarePosChannel_ptr->getPos();
00208       const stdair::ChannelLabel_T& lCurrentChannel =
00209         lCurrentFarePosChannel_ptr->getChannel();
00210 
00211       // Select the fare rules having a corresponding pos channel.
00212       if (lCurrentPointOfSale == lPointOfSale &&
00213           lCurrentChannel == lChannel) {
00214         _atLeastOneAvailablePosChannel = true;
00215         // Fare rule(s) with the same point-of-sale and channel exist(s), now
00216         // the time range need to be checked.
00217         const stdair::PosChannel& lFarePosChannel= *lCurrentFarePosChannel_ptr;
00218         priceQuote (iBookingRequest, ioTravelSolution, lFarePosChannel);
00219       }
00220     }
00221 
00222   }
00223 
00224   // //////////////////////////////////////////////////////////////////////
00225   void FareQuoter::
00226   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00227               stdair::TravelSolutionStruct& ioTravelSolution,
00228               const stdair::PosChannel& iFarePosChannel) {
00229 
00230     // Get the first segment path parsed key.
00231     const stdair::ParsedKey lFirstSPParsedKey =
00232       getFirstSPParsedKey(ioTravelSolution);
00233       
00234     // Get the segment boarding time of the segment path.
00235     const stdair::Duration_T& lSPTime = lFirstSPParsedKey.getBoardingTime();
00236 
00237     // Get the list of the fare rules time period.
00238     const stdair::TimePeriodList_T& lFareTimePeriodList =
00239       stdair::BomManager::getList<stdair::TimePeriod> (iFarePosChannel);
00240 
00241     // Browse the list of the fare rules time range.
00242     for (stdair::TimePeriodList_T::const_iterator itTimeRange =
00243            lFareTimePeriodList.begin();
00244          itTimeRange != lFareTimePeriodList.end();
00245          ++itTimeRange) {
00246       const stdair::TimePeriod* lCurrentFareTimePeriod_ptr = *itTimeRange ;
00247       assert (lCurrentFareTimePeriod_ptr != NULL);
00248 
00249       // Select the fare rules having a corresponding time range.
00250       const bool isDepartureTimeValid =
00251         lCurrentFareTimePeriod_ptr->isDepartureTimeValid (lSPTime);
00252 
00253       // If a fare rule has a corresponding time range, its advanced purchase,
00254       // trip type and minimum stay duration need to be checked.
00255       if (isDepartureTimeValid) {
00256         _atLeastOneAvailableTimeRule = true;
00257         const stdair::TimePeriod& lCurrentFareTimePeriod =
00258           *lCurrentFareTimePeriod_ptr;
00259         priceQuote (iBookingRequest, ioTravelSolution,
00260                     lCurrentFareTimePeriod, iFarePosChannel);
00261       }
00262     }
00263 
00264   }
00265 
00266   // //////////////////////////////////////////////////////////////////////
00267   void FareQuoter::
00268   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00269               stdair::TravelSolutionStruct& ioTravelSolution,
00270               const stdair::TimePeriod& iFareTimePeriod,
00271               const stdair::PosChannel& iFarePosChannel) {
00272 
00273     // Get the stay duration of the booking request.
00274     const stdair::DayDuration_T& lStayDuration=
00275       iBookingRequest.getStayDuration();
00276 
00277     // Get the booking request trip type.
00278     const stdair::TripType_T& lTripType =
00279       iBookingRequest.getTripType();
00280 
00281     // Get the booking request date time.
00282     const stdair::DateTime_T& lRequestDateTime =
00283       iBookingRequest.getRequestDateTime();
00284     
00285     // Get the referenced departure date of the segment path.
00286     const stdair::ParsedKey lFirstSPParsedKey =
00287       getFirstSPParsedKey(ioTravelSolution);
00288     const stdair::Date_T& lSPDate =
00289       lFirstSPParsedKey.getFlightDateKey().getDepartureDate();
00290 
00291     // Get the segment boarding time of the segment path.
00292     const stdair::Duration_T& lSPTime = lFirstSPParsedKey.getBoardingTime();
00293 
00294     // Construct the date-time type correponding to the flight date
00295     const stdair::DateTime_T lSPDateTime (lSPDate, lSPTime);
00296 
00297     bool isTripTypeValid = false;
00298     bool isStayDurationValid = false;
00299     bool isAdvancePurchaseValid = false;
00300 
00301     // Get the list of the fare features.
00302     const stdair::FareFeaturesList_T& lFareFeaturesList =
00303       stdair::BomManager::getList<stdair::FareFeatures> (iFareTimePeriod);
00304 
00305     // Browse the list of the fare rules features.
00306     for (stdair::FareFeaturesList_T::const_iterator itFareFeatures =
00307            lFareFeaturesList.begin();
00308          itFareFeatures != lFareFeaturesList.end();
00309          ++itFareFeatures) {
00310       const stdair::FareFeatures* lCurrentFareFeatures_ptr =
00311         *itFareFeatures;
00312       assert (lCurrentFareFeatures_ptr != NULL);
00313 
00314       // Does the current fare features correspond to a correct trip
00315       // type?
00316       isTripTypeValid =
00317         lCurrentFareFeatures_ptr->isTripTypeValid (lTripType);
00318       // Does the current fare features correspond to a correct stay
00319       // duration?
00320       isStayDurationValid =
00321         lCurrentFareFeatures_ptr->isStayDurationValid (lStayDuration);
00322       // Does the current fare features correspond to a correct advanced
00323       // purchase?
00324       isAdvancePurchaseValid = lCurrentFareFeatures_ptr->
00325         isAdvancePurchaseValid (lRequestDateTime,
00326                                 lSPDateTime);
00327         
00328       // Search for the fare rules having corresponding features.
00329       if (isStayDurationValid && isAdvancePurchaseValid && isTripTypeValid){
00330         _atLeastOneAvailableFeaturesRule = true;
00331         // Create a fare structure for the travel solution.
00332         stdair::FareOptionStruct lFareOption;
00333         const stdair::ChangeFees_T& lChangeFees =
00334           lCurrentFareFeatures_ptr->getChangeFees();
00335         // Set the fare change fees.
00336         lFareOption.setChangeFees (lChangeFees);
00337         const stdair::NonRefundable_T& lNonRefundable =
00338           lCurrentFareFeatures_ptr->getRefundableOption();
00339         // Set the fare refundable option.
00340         lFareOption.setNonRefundable (lNonRefundable);
00341         const stdair::SaturdayStay_T& lSaturdayStay =
00342           lCurrentFareFeatures_ptr->getSaturdayStay();
00343         // Set the fare saturday night stay option.
00344         lFareOption.setSaturdayStay (lSaturdayStay);
00345         const stdair::FareFeatures& lCurrentFareFeatures =
00346           *lCurrentFareFeatures_ptr;
00347         priceQuote (iBookingRequest, ioTravelSolution,
00348                     lCurrentFareFeatures, iFarePosChannel,
00349                     lFareOption);
00350       }
00351     }
00352     
00353   }
00354 
00355   
00356   // //////////////////////////////////////////////////////////////////////
00357   void FareQuoter::
00358   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00359               stdair::TravelSolutionStruct& ioTravelSolution,
00360               const stdair::FareFeatures& iFareFeatures,
00361               const stdair::PosChannel& iFarePosChannel,
00362               stdair::FareOptionStruct& iFareOption) {
00363 
00364     // Get the first segment path parsed key.
00365     const stdair::ParsedKey lFirstSPParsedKey =
00366       getFirstSPParsedKey(ioTravelSolution);
00367     
00368     // Get the segment-path of the travel solution.
00369     const stdair::SegmentPath_T& lSegmentPath =
00370       ioTravelSolution.getSegmentPath();
00371 
00372     // Get the list of the fare rules.
00373     const stdair::AirlineClassListList_T& lAirlineClassListList =
00374       stdair::BomManager::getList<stdair::AirlineClassList> (iFareFeatures);
00375 
00376     bool lCorrectAirlineRule = false;
00377     bool lAtLeastOneDifferentAirline = false; 
00378 
00379     // Browse the list of airline code list and search for the fare rules
00380     // having a corresponding airline list.
00381     for (stdair::AirlineClassListList_T::const_iterator itAirlineClassList =
00382            lAirlineClassListList.begin();
00383          itAirlineClassList != lAirlineClassListList.end();
00384          ++itAirlineClassList) {
00385       const stdair::AirlineClassList* lCurrentAirlineClassList_ptr =
00386         *itAirlineClassList;
00387       assert (lCurrentAirlineClassList_ptr != NULL);
00388 
00389       lCorrectAirlineRule = true;
00390       lAtLeastOneDifferentAirline = false;
00391         
00392       const stdair::ClassList_StringList_T lClassList_StringList =
00393         lCurrentAirlineClassList_ptr->getAirlineCodeList();
00394 
00395       // Compare the segment path airline list with the fare rule airline list.
00396       if (lClassList_StringList.size() == lSegmentPath.size()) {
00397         // If the two sizes are equal, we need to compare the airline codes.
00398         stdair::SegmentPath_T::const_iterator itSegmentPath =
00399           lSegmentPath.begin();
00400 
00401         stdair::ClassList_StringList_T::const_iterator itClassList_String =
00402           lClassList_StringList.begin();
00403         // Browse the segment path airline code list (while the segment path
00404         // airline list is equal to the fare rule airline list).
00405         while (itSegmentPath != lSegmentPath.end()
00406                && lAtLeastOneDifferentAirline == false) {
00407 
00408           // Get the segment airline code.
00409           const std::string lSegmentDateKey = *itSegmentPath;
00410           const stdair::ParsedKey& lParsedKey =
00411             stdair::BomKeyManager::extractKeys (lSegmentDateKey);
00412           const stdair::InventoryKey& lInventoryKey =
00413             lParsedKey.getInventoryKey();
00414           const stdair::AirlineCode_T& lSegmentAirlineCode =
00415             lInventoryKey.getAirlineCode();
00416 
00417           // Get the fare rule airline code.
00418           const stdair::AirlineCode_T& lFareRuleAirlineCode =
00419             *itClassList_String;
00420 
00421           if (lSegmentAirlineCode != lFareRuleAirlineCode) {
00422             lAtLeastOneDifferentAirline = true;
00423           }
00424           itSegmentPath++;
00425           itClassList_String++;
00426         }      
00427 
00428       } else {
00429         // If the two sizes are different, the fare rule does not match the
00430         // travel solution into question.
00431         lCorrectAirlineRule = false;
00432       }
00433       
00434       // If one segment airline code and one fare rule airline code are
00435       // different then the fare rule does not match the travel solution.
00436       if (lAtLeastOneDifferentAirline == true) {
00437         lCorrectAirlineRule = false;
00438       }
00439 
00440       // If the current fare rule is a match, add the fare option structure
00441       // to the travel solution into question.
00442       if (lCorrectAirlineRule == true) {
00443         _atLeastOneAvailableAirlineClassRule = true;
00444         // Get the booking request trip type.
00445         const stdair::TripType_T& lTripType =
00446           iBookingRequest.getTripType();
00447 
00448         // Get the travel fare.
00449         stdair::Fare_T lFare =
00450           lCurrentAirlineClassList_ptr->getFare();
00451         // If the trip into question is the inbound or outbound part of a round trip,
00452         // the applicable fare is a half RT fare.
00453         if (lTripType == "RI" || lTripType == "RO") {
00454           lFare /= 2;
00455         }
00456         // Set the travel fare option.
00457         iFareOption.setFare (lFare);
00458         // Copy the class path list into the fare option.
00459         const stdair::ClassList_StringList_T& lClassCodeList =
00460           lCurrentAirlineClassList_ptr->getClassCodeList();
00461         for (stdair::ClassList_StringList_T::const_iterator itClassCodeList =
00462                lClassCodeList.begin();
00463              itClassCodeList != lClassCodeList.end(); ++itClassCodeList ) {
00464           const stdair::ClassList_String_T& lClassCodeList = *itClassCodeList;
00465           iFareOption.addClassList (lClassCodeList);
00466         }
00467 
00468         // Add the fare option to the travel solution into question.
00469         ioTravelSolution.addFareOption (iFareOption);
00470           
00471         // DEBUG
00472         STDAIR_LOG_DEBUG ("Segment path: " << lFirstSPParsedKey.toString()
00473                           << ". A corresponding fare option for the '"
00474                           << lCurrentAirlineClassList_ptr->describeKey()
00475                           << "' class is: " << iFareOption);
00476 
00477         iFareOption.emptyClassList();
00478       }
00479     }
00480 
00481   }
00482 
00483   // //////////////////////////////////////////////////////////////////////
00484   stdair::ParsedKey FareQuoter::
00485   getFirstSPParsedKey (stdair::TravelSolutionStruct& ioTravelSolution) {
00486 
00487     // Get the segment-path of the travel solution.
00488     const stdair::SegmentPath_T& lSegmentPath =
00489       ioTravelSolution.getSegmentPath();  
00490 
00491     // Get the number of segments of the travel solution.
00492     const stdair::NbOfSegments_T& lNbSegments = lSegmentPath.size();
00493 
00494     // Sanity check: there is at least one segment in the travel solution.
00495     assert (lNbSegments >= 1);
00496     
00497     // Get the first segment of the travel solution.
00498     const std::string& lFirstSegmentDateKey = lSegmentPath.front();
00499 
00500     // Get the parsed key of the first segment of the travel solution.
00501     const stdair::ParsedKey& lFirstSegmentParsedKey =
00502       stdair::BomKeyManager::extractKeys (lFirstSegmentDateKey);
00503 
00504     return lFirstSegmentParsedKey;
00505     
00506   }
00507 
00508   // //////////////////////////////////////////////////////////////////////
00509   stdair::ParsedKey FareQuoter::
00510   getLastSPParsedKey (stdair::TravelSolutionStruct& ioTravelSolution) {
00511 
00512     // Get the segment-path of the travel solution.
00513     const stdair::SegmentPath_T& lSegmentPath =
00514       ioTravelSolution.getSegmentPath();  
00515 
00516     // Get the number of segments of the travel solution.
00517     const stdair::NbOfSegments_T& lNbSegments = lSegmentPath.size();
00518 
00519     // Sanity check: there is at least one segment in the travel solution.
00520     assert (lNbSegments >= 1);
00521     
00522     // Get the last segment of the travel solution.
00523     const std::string& lLastSegmentDateKey = lSegmentPath.back();
00524 
00525     // Get the parsed key of the last segment of the travel solution.
00526     const stdair::ParsedKey& lLastSegmentParsedKey =
00527       stdair::BomKeyManager::extractKeys (lLastSegmentDateKey);
00528 
00529     return lLastSegmentParsedKey;
00530     
00531   }
00532 
00533   // //////////////////////////////////////////////////////////////////////
00534   void FareQuoter::
00535   displayMissingFareRuleMessage (const stdair::BookingRequestStruct& iBookingRequest,
00536                                  stdair::TravelSolutionStruct& ioTravelSolution) {
00537 
00538     // Get the origin of the first segment in order to get the origin of
00539     // the solution.    
00540     const stdair::ParsedKey lFirstSPParsedKey =
00541       getFirstSPParsedKey(ioTravelSolution);
00542     const stdair::AirportCode_T& lOrigin = lFirstSPParsedKey._boardingPoint;
00543 
00544     // Get the destination of the last segment in order to get the
00545     // destination of the solution.
00546     const stdair::ParsedKey& lLastSegmentKey =
00547       getLastSPParsedKey(ioTravelSolution);
00548     const stdair::AirportCode_T& lDestination = lLastSegmentKey._offPoint;
00549 
00550     // Construct the Airport pair stream of the segment path.
00551     const stdair::AirportPairKey lAirportPairKey (lOrigin, lDestination);
00552 
00553     // Get the date of the first segment date key.
00554     const stdair::FlightDateKey& lFlightDateKey =
00555       lFirstSPParsedKey.getFlightDateKey();
00556 
00557     // Get the point-of-sale of the booking request.
00558     const stdair::CityCode_T& lPointOfSale = iBookingRequest.getPOS();
00559     // Get the booking request channel.
00560     const stdair::ChannelLabel_T& lChannel =
00561       iBookingRequest.getBookingChannel();
00562     // Construct the corresponding POS-channel primary key.
00563     const stdair::PosChannelKey lFarePosChannelKey (lPointOfSale, lChannel);
00564 
00565     // Get the booking request date time.
00566     const stdair::DateTime_T& lRequestDateTime =
00567       iBookingRequest.getRequestDateTime();
00568     
00569     // If no fare rule has a corresponding date range, the pricing is not
00570     // possible, throw an exception.
00571     if (_atLeastOneAvailableDateRule == false) {
00572       const stdair::SegmentDateKey lSegmentDateKey =
00573         lFirstSPParsedKey.getSegmentKey();
00574       STDAIR_LOG_ERROR ("No available fare rule corresponding to the "
00575                         "flight date " << lFlightDateKey.toString()
00576                         << " and the Origin-Destination pair: "
00577                         << lSegmentDateKey.toString());
00578       throw FlightDateNotFoundException ("No available fare rule for the "
00579                                          "flight date "
00580                                          + lFlightDateKey.toString()
00581                                          + " and the Origin-Destination pair: "
00582                                          + lSegmentDateKey.toString());
00583     }
00584     // If no fare rule has a corresponding pos channel, the pricing is not possible,
00585     // throw an exception.
00586     else if (_atLeastOneAvailablePosChannel == false) {
00587       STDAIR_LOG_ERROR ("No available fare rule corresponding to the "
00588                         "point of sale " << lPointOfSale
00589                         << ", to the channel " << lChannel
00590                         << ", to the flight date "
00591                         << lFlightDateKey.toString()
00592                         << " and to the Origin-Destination pair: "
00593                         << lAirportPairKey.toString());
00594       throw PosOrChannelNotFoundException ("No available fare rule for the "
00595                                            "point of sale " + lPointOfSale
00596                                            + ", the channel " + lChannel
00597                                            + ", the flight date "
00598                                            + lFlightDateKey.toString()
00599                                            + " and the Origin-Destination pair: "
00600                                            + lAirportPairKey.toString());
00601     }
00602     // If no fare rule has a corresponding time range, the pricing is not possible,
00603     // throw an exception.
00604     else if (_atLeastOneAvailableTimeRule == false) {
00605       STDAIR_LOG_ERROR ("No available fare rule corresponding to '"
00606                         << lFirstSPParsedKey.toString() << "' (parsed key) and to '"
00607                         << lFarePosChannelKey.toString() << "' (POS and channel)");
00608       throw FlightTimeNotFoundException ("No available fare rule corresponding "
00609                                          "to '" + lFirstSPParsedKey.toString()
00610                                          + "' (parsed key) and to '"
00611                                          + lFarePosChannelKey.toString()
00612                                          + "' (POS and channel)");
00613     }
00614     // If no fare rule matches the advance purchase, trip type and stay
00615     // duration criterion, the pricing is not possible, throw an exception.
00616     else if (_atLeastOneAvailableFeaturesRule == false) {
00617       // Get the stay duration of the booking request.
00618       const stdair::DayDuration_T& lStayDuration=
00619         iBookingRequest.getStayDuration();
00620       std::ostringstream lStayDurationStream;
00621       lStayDurationStream << lStayDuration;
00622       const std::string lStayDurationString (lStayDurationStream.str());
00623 
00624       // Get the booking request trip type.
00625       const stdair::TripType_T& lTripType =
00626         iBookingRequest.getTripType();
00627 
00628       STDAIR_LOG_ERROR ("No available fare rule corresponding to a "
00629                         "trip type " << lTripType
00630                         << ", to a stay duration of " <<  lStayDurationString
00631                         << ", to a request date time of " << lRequestDateTime
00632                         << ", to '" << lFirstSPParsedKey.toString()
00633                         << "' (parsed key) and to '"
00634                         << lFarePosChannelKey << "' (POS and channel)");
00635       throw FeaturesNotFoundException ("No available fare rule corresponding to a "
00636                                        "trip type " + lTripType
00637                                        + ", to a stay duration of "
00638                                        + lStayDurationString
00639                                        + ", to a request date time of "
00640                                        + boost::posix_time::to_simple_string(lRequestDateTime)
00641                                        + ", to '" + lFirstSPParsedKey.toString()
00642                                        + "' (parsed key) and to '"
00643                                        + lFarePosChannelKey.toString()
00644                                        + "' (POS and channel)");
00645     }
00646     assert (_atLeastOneAvailableAirlineClassRule == false);
00647     // If no fare rule matches the airline class path, the pricing is not
00648     // possible, throw an exception.
00649     STDAIR_LOG_ERROR ("No available fare rule corresponding to '"
00650                       << lFirstSPParsedKey .toString() << "' (parsed key), to '"
00651                       << iBookingRequest.describe()
00652                       << "' (booking request) and to '"
00653                       << lFarePosChannelKey.toString() << "' (POS and channel)");
00654     throw AirlineNotFoundException ("No available fare rule corresponding to '"
00655                                     + lFirstSPParsedKey .toString()
00656                                     + "' (parsed key), to '"
00657                                     + iBookingRequest.describe()
00658                                     + "' (booking request) and to '"
00659                                     + lFarePosChannelKey.toString()
00660                                     + "' (POS and channel)");
00661   }
00662 }
00663