$treeview $search $mathjax
SimFQT Logo  1.00.0
$projectbrief
$projectbrief
$searchbox

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/BasConst_BomDisplay.hpp>
00009 #include <stdair/basic/BasConst_Request.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 || lCurrentPointOfSale == stdair::DEFAULT_POS) {
00213         if (lCurrentChannel == lChannel || lCurrentChannel == stdair::DEFAULT_CHANNEL) {
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           STDAIR_LOG_DEBUG (lCurrentPointOfSale + " " + lCurrentChannel);
00219           priceQuote (iBookingRequest, ioTravelSolution, lFarePosChannel);
00220         }
00221       }
00222     }
00223 
00224   }
00225 
00226   // //////////////////////////////////////////////////////////////////////
00227   void FareQuoter::
00228   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00229               stdair::TravelSolutionStruct& ioTravelSolution,
00230               const stdair::PosChannel& iFarePosChannel) {
00231 
00232     // Get the first segment path parsed key.
00233     const stdair::ParsedKey lFirstSPParsedKey =
00234       getFirstSPParsedKey(ioTravelSolution);
00235       
00236     // Get the segment boarding time of the segment path.
00237     const stdair::Duration_T& lSPTime = lFirstSPParsedKey.getBoardingTime();
00238 
00239     // Get the list of the fare rules time period.
00240     const stdair::TimePeriodList_T& lFareTimePeriodList =
00241       stdair::BomManager::getList<stdair::TimePeriod> (iFarePosChannel);
00242 
00243     // Browse the list of the fare rules time range.
00244     for (stdair::TimePeriodList_T::const_iterator itTimeRange =
00245            lFareTimePeriodList.begin();
00246          itTimeRange != lFareTimePeriodList.end();
00247          ++itTimeRange) {
00248       const stdair::TimePeriod* lCurrentFareTimePeriod_ptr = *itTimeRange ;
00249       assert (lCurrentFareTimePeriod_ptr != NULL);
00250 
00251       // Select the fare rules having a corresponding time range.
00252       const bool isDepartureTimeValid =
00253         lCurrentFareTimePeriod_ptr->isDepartureTimeValid (lSPTime);
00254 
00255       // If a fare rule has a corresponding time range, its advanced purchase,
00256       // trip type and minimum stay duration need to be checked.
00257       if (isDepartureTimeValid) {
00258         _atLeastOneAvailableTimeRule = true;
00259         const stdair::TimePeriod& lCurrentFareTimePeriod =
00260           *lCurrentFareTimePeriod_ptr;
00261         priceQuote (iBookingRequest, ioTravelSolution,
00262                     lCurrentFareTimePeriod, iFarePosChannel);
00263       }
00264     }
00265 
00266   }
00267 
00268   // //////////////////////////////////////////////////////////////////////
00269   void FareQuoter::
00270   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00271               stdair::TravelSolutionStruct& ioTravelSolution,
00272               const stdair::TimePeriod& iFareTimePeriod,
00273               const stdair::PosChannel& iFarePosChannel) {
00274 
00275     // Get the stay duration of the booking request.
00276     const stdair::DayDuration_T& lStayDuration=
00277       iBookingRequest.getStayDuration();
00278 
00279     // Get the booking request trip type.
00280     const stdair::TripType_T& lTripType =
00281       iBookingRequest.getTripType();
00282 
00283     // Get the booking request date time.
00284     const stdair::DateTime_T& lRequestDateTime =
00285       iBookingRequest.getRequestDateTime();
00286     
00287     // Get the referenced departure date of the segment path.
00288     const stdair::ParsedKey lFirstSPParsedKey =
00289       getFirstSPParsedKey(ioTravelSolution);
00290     const stdair::Date_T& lSPDate =
00291       lFirstSPParsedKey.getFlightDateKey().getDepartureDate();
00292 
00293     // Get the segment boarding time of the segment path.
00294     const stdair::Duration_T& lSPTime = lFirstSPParsedKey.getBoardingTime();
00295 
00296     // Construct the date-time type correponding to the flight date
00297     const stdair::DateTime_T lSPDateTime (lSPDate, lSPTime);
00298 
00299     bool isTripTypeValid = false;
00300     bool isStayDurationValid = false;
00301     bool isAdvancePurchaseValid = false;
00302 
00303     // Get the list of the fare features (if such list exists: the POS
00304     // and channel couple can be only present in a yield rule).
00305     const bool hasFareFeaturesList =
00306       stdair::BomManager::hasList<stdair::FareFeatures> (iFareTimePeriod);
00307     if (hasFareFeaturesList == false) {
00308       return;
00309     }
00310     assert (hasFareFeaturesList == true);
00311     const stdair::FareFeaturesList_T& lFareFeaturesList =
00312       stdair::BomManager::getList<stdair::FareFeatures> (iFareTimePeriod);
00313 
00314     // Browse the list of the fare rules features.
00315     for (stdair::FareFeaturesList_T::const_iterator itFareFeatures =
00316            lFareFeaturesList.begin();
00317          itFareFeatures != lFareFeaturesList.end();
00318          ++itFareFeatures) {
00319       const stdair::FareFeatures* lCurrentFareFeatures_ptr =
00320         *itFareFeatures;
00321       assert (lCurrentFareFeatures_ptr != NULL);
00322 
00323       // Does the current fare features correspond to a correct trip
00324       // type?
00325       isTripTypeValid =
00326         lCurrentFareFeatures_ptr->isTripTypeValid (lTripType);
00327       // Does the current fare features correspond to a correct stay
00328       // duration?
00329       isStayDurationValid =
00330         lCurrentFareFeatures_ptr->isStayDurationValid (lStayDuration);
00331       // Does the current fare features correspond to a correct advanced
00332       // purchase?
00333       isAdvancePurchaseValid = lCurrentFareFeatures_ptr->
00334         isAdvancePurchaseValid (lRequestDateTime,
00335                                 lSPDateTime);
00336         
00337       // Search for the fare rules having corresponding features.
00338       if (isStayDurationValid && isAdvancePurchaseValid && isTripTypeValid){
00339         _atLeastOneAvailableFeaturesRule = true;
00340         // Create a fare structure for the travel solution.
00341         stdair::FareOptionStruct lFareOption;
00342         const stdair::ChangeFees_T& lChangeFees =
00343           lCurrentFareFeatures_ptr->getChangeFees();
00344         // Set the fare change fees.
00345         lFareOption.setChangeFees (lChangeFees);
00346         const stdair::NonRefundable_T& lNonRefundable =
00347           lCurrentFareFeatures_ptr->getRefundableOption();
00348         // Set the fare refundable option.
00349         lFareOption.setNonRefundable (lNonRefundable);
00350         const stdair::SaturdayStay_T& lSaturdayStay =
00351           lCurrentFareFeatures_ptr->getSaturdayStay();
00352         // Set the fare saturday night stay option.
00353         lFareOption.setSaturdayStay (lSaturdayStay);
00354         const stdair::FareFeatures& lCurrentFareFeatures =
00355           *lCurrentFareFeatures_ptr;
00356         priceQuote (iBookingRequest, ioTravelSolution,
00357                     lCurrentFareFeatures, iFarePosChannel,
00358                     lFareOption);
00359       }
00360     }
00361     
00362   }
00363 
00364   
00365   // //////////////////////////////////////////////////////////////////////
00366   void FareQuoter::
00367   priceQuote (const stdair::BookingRequestStruct& iBookingRequest,
00368               stdair::TravelSolutionStruct& ioTravelSolution,
00369               const stdair::FareFeatures& iFareFeatures,
00370               const stdair::PosChannel& iFarePosChannel,
00371               stdair::FareOptionStruct& iFareOption) {
00372     
00373     // Get the segment-path of the travel solution.
00374     const stdair::SegmentPath_T& lSegmentPath =
00375       ioTravelSolution.getSegmentPath();
00376 
00377     // Get the list of the fare rules.
00378     const stdair::AirlineClassListList_T& lAirlineClassListList =
00379       stdair::BomManager::getList<stdair::AirlineClassList> (iFareFeatures);
00380 
00381     bool lCorrectAirlineRule = false;
00382     bool lAtLeastOneDifferentAirline = false; 
00383 
00384     // Browse the list of airline code list and search for the fare rules
00385     // having a corresponding airline list.
00386     for (stdair::AirlineClassListList_T::const_iterator itAirlineClassList =
00387            lAirlineClassListList.begin();
00388          itAirlineClassList != lAirlineClassListList.end();
00389          ++itAirlineClassList) {
00390       const stdair::AirlineClassList* lCurrentAirlineClassList_ptr =
00391         *itAirlineClassList;
00392       assert (lCurrentAirlineClassList_ptr != NULL);
00393 
00394       lCorrectAirlineRule = true;
00395       lAtLeastOneDifferentAirline = false;
00396         
00397       const stdair::ClassList_StringList_T lClassList_StringList =
00398         lCurrentAirlineClassList_ptr->getAirlineCodeList();
00399 
00400       // Compare the segment path airline list with the fare rule airline list.
00401       if (lClassList_StringList.size() == lSegmentPath.size()) {
00402         // If the two sizes are equal, we need to compare the airline codes.
00403         stdair::SegmentPath_T::const_iterator itSegmentPath =
00404           lSegmentPath.begin();
00405 
00406         stdair::ClassList_StringList_T::const_iterator itClassList_String =
00407           lClassList_StringList.begin();
00408         // Browse the segment path airline code list (while the segment path
00409         // airline list is equal to the fare rule airline list).
00410         while (itSegmentPath != lSegmentPath.end()
00411                && lAtLeastOneDifferentAirline == false) {
00412 
00413           // Get the segment airline code.
00414           const std::string lSegmentDateKey = *itSegmentPath;
00415           const stdair::ParsedKey& lParsedKey =
00416             stdair::BomKeyManager::extractKeys (lSegmentDateKey);
00417           const stdair::InventoryKey& lInventoryKey =
00418             lParsedKey.getInventoryKey();
00419           const stdair::AirlineCode_T& lSegmentAirlineCode =
00420             lInventoryKey.getAirlineCode();
00421 
00422           // Get the fare rule airline code.
00423           const stdair::AirlineCode_T& lFareRuleAirlineCode =
00424             *itClassList_String;
00425 
00426           if (lSegmentAirlineCode != lFareRuleAirlineCode) {
00427             lAtLeastOneDifferentAirline = true;
00428           }
00429           itSegmentPath++;
00430           itClassList_String++;
00431         }      
00432 
00433       } else {
00434         // If the two sizes are different, the fare rule does not match the
00435         // travel solution into question.
00436         lCorrectAirlineRule = false;
00437       }
00438       
00439       // If one segment airline code and one fare rule airline code are
00440       // different then the fare rule does not match the travel solution.
00441       if (lAtLeastOneDifferentAirline == true) {
00442         lCorrectAirlineRule = false;
00443       }
00444 
00445       // If the current fare rule is a match, add the fare option structure
00446       // to the travel solution into question.
00447       if (lCorrectAirlineRule == true) {
00448         _atLeastOneAvailableAirlineClassRule = true;
00449         // Get the booking request trip type.
00450         const stdair::TripType_T& lTripType =
00451           iBookingRequest.getTripType();
00452 
00453         // Get the travel fare.
00454         stdair::Fare_T lFare =
00455           lCurrentAirlineClassList_ptr->getFare();
00456         // If the trip into question is the inbound or outbound part of a round trip,
00457         // the applicable fare is a half RT fare.
00458         if (lTripType == "RI" || lTripType == "RO") {
00459           lFare /= 2;
00460         }
00461         // Set the travel fare option.
00462         iFareOption.setFare (lFare);
00463         // Copy the class path list into the fare option.
00464         const stdair::ClassList_StringList_T& lClassCodeList =
00465           lCurrentAirlineClassList_ptr->getClassCodeList();
00466         for (stdair::ClassList_StringList_T::const_iterator itClassCodeList =
00467                lClassCodeList.begin();
00468              itClassCodeList != lClassCodeList.end(); ++itClassCodeList ) {
00469           const stdair::ClassList_String_T& lClassCodeList = *itClassCodeList;
00470           iFareOption.addClassList (lClassCodeList);
00471         }
00472 
00473         // Add the fare option to the travel solution into question.
00474         ioTravelSolution.addFareOption (iFareOption);
00475           
00476         // DEBUG
00477         STDAIR_LOG_DEBUG (ioTravelSolution.describeSegmentPath()
00478                           << ". A corresponding fare option for the '"
00479                           << lCurrentAirlineClassList_ptr->describeKey()
00480                           << "' class is: " << iFareOption);
00481 
00482         iFareOption.emptyClassList();
00483       }
00484     }
00485 
00486   }
00487 
00488   // //////////////////////////////////////////////////////////////////////
00489   stdair::ParsedKey FareQuoter::
00490   getFirstSPParsedKey (stdair::TravelSolutionStruct& ioTravelSolution) {
00491 
00492     // Get the segment-path of the travel solution.
00493     const stdair::SegmentPath_T& lSegmentPath =
00494       ioTravelSolution.getSegmentPath();  
00495 
00496     // Get the number of segments of the travel solution.
00497     const stdair::NbOfSegments_T& lNbSegments = lSegmentPath.size();
00498 
00499     // Sanity check: there is at least one segment in the travel solution.
00500     assert (lNbSegments >= 1);
00501     
00502     // Get the first segment of the travel solution.
00503     const std::string& lFirstSegmentDateKey = lSegmentPath.front();
00504 
00505     // Get the parsed key of the first segment of the travel solution.
00506     const stdair::ParsedKey& lFirstSegmentParsedKey =
00507       stdair::BomKeyManager::extractKeys (lFirstSegmentDateKey);
00508 
00509     return lFirstSegmentParsedKey;
00510     
00511   }
00512 
00513   // //////////////////////////////////////////////////////////////////////
00514   stdair::ParsedKey FareQuoter::
00515   getLastSPParsedKey (stdair::TravelSolutionStruct& ioTravelSolution) {
00516 
00517     // Get the segment-path of the travel solution.
00518     const stdair::SegmentPath_T& lSegmentPath =
00519       ioTravelSolution.getSegmentPath();  
00520 
00521     // Get the number of segments of the travel solution.
00522     const stdair::NbOfSegments_T& lNbSegments = lSegmentPath.size();
00523 
00524     // Sanity check: there is at least one segment in the travel solution.
00525     assert (lNbSegments >= 1);
00526     
00527     // Get the last segment of the travel solution.
00528     const std::string& lLastSegmentDateKey = lSegmentPath.back();
00529 
00530     // Get the parsed key of the last segment of the travel solution.
00531     const stdair::ParsedKey& lLastSegmentParsedKey =
00532       stdair::BomKeyManager::extractKeys (lLastSegmentDateKey);
00533 
00534     return lLastSegmentParsedKey;
00535     
00536   }
00537 
00538   // //////////////////////////////////////////////////////////////////////
00539   void FareQuoter::
00540   displayMissingFareRuleMessage (const stdair::BookingRequestStruct& iBookingRequest,
00541                                  stdair::TravelSolutionStruct& ioTravelSolution) {
00542 
00543     // Get the origin of the first segment in order to get the origin of
00544     // the solution.    
00545     const stdair::ParsedKey lFirstSPParsedKey =
00546       getFirstSPParsedKey(ioTravelSolution);
00547     const stdair::AirportCode_T& lOrigin = lFirstSPParsedKey._boardingPoint;
00548 
00549     // Get the destination of the last segment in order to get the
00550     // destination of the solution.
00551     const stdair::ParsedKey& lLastSegmentKey =
00552       getLastSPParsedKey(ioTravelSolution);
00553     const stdair::AirportCode_T& lDestination = lLastSegmentKey._offPoint;
00554 
00555     // Construct the Airport pair stream of the segment path.
00556     const stdair::AirportPairKey lAirportPairKey (lOrigin, lDestination);
00557 
00558     // Get the date of the first segment date key.
00559     const stdair::FlightDateKey& lFlightDateKey =
00560       lFirstSPParsedKey.getFlightDateKey();
00561 
00562     // Get the point-of-sale of the booking request.
00563     const stdair::CityCode_T& lPointOfSale = iBookingRequest.getPOS();
00564     // Get the booking request channel.
00565     const stdair::ChannelLabel_T& lChannel =
00566       iBookingRequest.getBookingChannel();
00567     // Construct the corresponding POS-channel primary key.
00568     const stdair::PosChannelKey lFarePosChannelKey (lPointOfSale, lChannel);
00569 
00570     // Get the booking request date time.
00571     const stdair::DateTime_T& lRequestDateTime =
00572       iBookingRequest.getRequestDateTime();
00573     
00574     // If no fare rule has a corresponding date range, the pricing is not
00575     // possible, throw an exception.
00576     if (_atLeastOneAvailableDateRule == false) {
00577       const stdair::SegmentDateKey lSegmentDateKey =
00578         lFirstSPParsedKey.getSegmentKey();
00579       STDAIR_LOG_ERROR ("No available fare rule corresponding to the "
00580                         "flight date " << lFlightDateKey.toString()
00581                         << " and the Origin-Destination pair: "
00582                         << lSegmentDateKey.toString());
00583       throw FlightDateNotFoundException ("No available fare rule for the "
00584                                          "flight date "
00585                                          + lFlightDateKey.toString()
00586                                          + " and the Origin-Destination pair: "
00587                                          + lSegmentDateKey.toString());
00588     }
00589     // If no fare rule has a corresponding pos channel, the pricing is not possible,
00590     // throw an exception.
00591     else if (_atLeastOneAvailablePosChannel == false) {
00592       STDAIR_LOG_ERROR ("No available fare rule corresponding to the "
00593                         "point of sale " << lPointOfSale
00594                         << ", to the channel " << lChannel
00595                         << ", to the flight date "
00596                         << lFlightDateKey.toString()
00597                         << " and to the Origin-Destination pair: "
00598                         << lAirportPairKey.toString());
00599       throw PosOrChannelNotFoundException ("No available fare rule for the "
00600                                            "point of sale " + lPointOfSale
00601                                            + ", the channel " + lChannel
00602                                            + ", the flight date "
00603                                            + lFlightDateKey.toString()
00604                                            + " and the Origin-Destination pair: "
00605                                            + lAirportPairKey.toString());
00606     }
00607     // If no fare rule has a corresponding time range, the pricing is not possible,
00608     // throw an exception.
00609     else if (_atLeastOneAvailableTimeRule == false) {
00610       STDAIR_LOG_ERROR ("No available fare rule corresponding to '"
00611                         << lFirstSPParsedKey.toString() << "' (parsed key) and to '"
00612                         << lFarePosChannelKey.toString() << "' (POS and channel)");
00613       throw FlightTimeNotFoundException ("No available fare rule corresponding "
00614                                          "to '" + lFirstSPParsedKey.toString()
00615                                          + "' (parsed key) and to '"
00616                                          + lFarePosChannelKey.toString()
00617                                          + "' (POS and channel)");
00618     }
00619     // If no fare rule matches the advance purchase, trip type and stay
00620     // duration criterion, the pricing is not possible, throw an exception.
00621     else if (_atLeastOneAvailableFeaturesRule == false) {
00622       // Get the stay duration of the booking request.
00623       const stdair::DayDuration_T& lStayDuration=
00624         iBookingRequest.getStayDuration();
00625       std::ostringstream lStayDurationStream;
00626       lStayDurationStream << lStayDuration;
00627       const std::string lStayDurationString (lStayDurationStream.str());
00628 
00629       // Get the booking request trip type.
00630       const stdair::TripType_T& lTripType =
00631         iBookingRequest.getTripType();
00632 
00633       STDAIR_LOG_ERROR ("No available fare rule corresponding to a "
00634                         "trip type " << lTripType
00635                         << ", to a stay duration of " <<  lStayDurationString
00636                         << ", to a request date time of " << lRequestDateTime
00637                         << ", to '" << lFirstSPParsedKey.toString()
00638                         << "' (parsed key) and to '"
00639                         << lFarePosChannelKey << "' (POS and channel)");
00640       throw FeaturesNotFoundException ("No available fare rule corresponding to a "
00641                                        "trip type " + lTripType
00642                                        + ", to a stay duration of "
00643                                        + lStayDurationString
00644                                        + ", to a request date time of "
00645                                        + boost::posix_time::to_simple_string(lRequestDateTime)
00646                                        + ", to '" + lFirstSPParsedKey.toString()
00647                                        + "' (parsed key) and to '"
00648                                        + lFarePosChannelKey.toString()
00649                                        + "' (POS and channel)");
00650     }
00651     assert (_atLeastOneAvailableAirlineClassRule == false);
00652     // If no fare rule matches the airline class path, the pricing is not
00653     // possible, throw an exception.
00654     STDAIR_LOG_ERROR ("No available fare rule corresponding to '"
00655                       << lFirstSPParsedKey .toString() << "' (parsed key), to '"
00656                       << iBookingRequest.describe()
00657                       << "' (booking request) and to '"
00658                       << lFarePosChannelKey.toString() << "' (POS and channel)");
00659     throw AirlineNotFoundException ("No available fare rule corresponding to '"
00660                                     + lFirstSPParsedKey .toString()
00661                                     + "' (parsed key), to '"
00662                                     + iBookingRequest.describe()
00663                                     + "' (booking request) and to '"
00664                                     + lFarePosChannelKey.toString()
00665                                     + "' (POS and channel)");
00666   }
00667 }
00668