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