$treeview $search $mathjax
AirInv Logo  1.00.1
$projectbrief
$projectbrief
$searchbox

InventoryGenerator.cpp

Go to the documentation of this file.
00001 // //////////////////////////////////////////////////////////////////////
00002 // Import section
00003 // //////////////////////////////////////////////////////////////////////
00004 // STL
00005 #include <cassert>
00006 // Boost
00007 #include <boost/date_time/date_iterator.hpp>
00008 // StdAir
00009 #include <stdair/stdair_types.hpp>
00010 #include <stdair/basic/BasConst_Inventory.hpp>
00011 #include <stdair/basic/BasConst_SellUpCurves.hpp>
00012 #include <stdair/bom/BomManager.hpp>
00013 #include <stdair/bom/BomRoot.hpp>
00014 #include <stdair/bom/Inventory.hpp>
00015 #include <stdair/bom/AirlineFeature.hpp>
00016 #include <stdair/bom/FlightDate.hpp>
00017 #include <stdair/bom/SegmentDate.hpp>
00018 #include <stdair/bom/SegmentCabin.hpp>
00019 #include <stdair/bom/FareFamily.hpp>
00020 #include <stdair/bom/BookingClass.hpp>
00021 #include <stdair/bom/LegDate.hpp>
00022 #include <stdair/bom/LegCabin.hpp>
00023 #include <stdair/bom/SimpleNestingStructure.hpp>
00024 #include <stdair/bom/NestingNode.hpp>
00025 #include <stdair/bom/Policy.hpp>
00026 #include <stdair/bom/Bucket.hpp>  
00027 #include <stdair/bom/BomKeyManager.hpp>
00028 #include <stdair/factory/FacBomManager.hpp>
00029 #include <stdair/service/Logger.hpp>
00030 // AirInv
00031 #include <airinv/bom/FlightPeriodStruct.hpp>
00032 #include <airinv/command/InventoryGenerator.hpp>
00033 
00034 namespace AIRINV {
00035 
00036   // ////////////////////////////////////////////////////////////////////
00037   void InventoryGenerator::
00038   createFlightDate (stdair::BomRoot& ioBomRoot,
00039                     const FlightPeriodStruct& iFlightPeriod) {
00040     const stdair::AirlineCode_T& lAirlineCode = iFlightPeriod._airlineCode;
00041  
00042     // Instantiate an inventory object (if not exist)
00043     // for the given key (airline code)
00044     stdair::Inventory* lInventory_ptr = stdair::BomManager::
00045       getObjectPtr<stdair::Inventory> (ioBomRoot, lAirlineCode);
00046     if (lInventory_ptr == NULL) {
00047       stdair::InventoryKey lKey (lAirlineCode);
00048       lInventory_ptr =
00049         &stdair::FacBom<stdair::Inventory>::instance().create (lKey);
00050       stdair::FacBomManager::addToListAndMap (ioBomRoot, *lInventory_ptr);
00051       stdair::FacBomManager::linkWithParent (ioBomRoot, *lInventory_ptr);
00052 
00053       // Add the airline feature object to the inventory
00054       const stdair::AirlineFeatureKey lAirlineFeatureKey (lAirlineCode);
00055       stdair::AirlineFeature& lAirlineFeature =
00056         stdair::FacBom<stdair::AirlineFeature>::instance().create (lAirlineFeatureKey);
00057       stdair::FacBomManager::setAirlineFeature (*lInventory_ptr,
00058                                                 lAirlineFeature);
00059       stdair::FacBomManager::linkWithParent (*lInventory_ptr, lAirlineFeature);
00060       // Link the airline feature object with the top of the BOM tree
00061       stdair::FacBomManager::addToListAndMap (ioBomRoot, lAirlineFeature);
00062     }
00063     assert (lInventory_ptr != NULL);
00064     
00065     // Generate all the dates corresponding to the period
00066     // and create the corresponding flight-dates.
00067     const stdair::DatePeriod_T lDateRange = iFlightPeriod._dateRange;
00068 
00069     for (boost::gregorian::day_iterator itDate = lDateRange.begin();
00070          itDate != lDateRange.end(); ++itDate) {
00071       const stdair::Date_T& currentDate = *itDate;
00072 
00073       // Retrieve, for the current day, the Day-Of-the-Week (thanks to Boost)
00074       const unsigned short currentDoW = currentDate.day_of_week().as_number();
00075         
00076       // The FlightPeriod structure stores which Days (-Of-the-Week) are
00077       // active within the week. For each day (Mon., Tue., etc.), a boolean
00078       // states whether the Flight is active for that day.
00079       const stdair::DoWStruct& lDoWList = iFlightPeriod._dow;
00080       const bool isDoWActive = lDoWList.getStandardDayOfWeek (currentDoW);
00081 
00082       if (isDoWActive == true) {
00083         createFlightDate (ioBomRoot, *lInventory_ptr, currentDate,
00084                           iFlightPeriod);
00085       }
00086     }
00087   }
00088   
00089   // ////////////////////////////////////////////////////////////////////
00090   void InventoryGenerator::
00091   createFlightDate (stdair::BomRoot& ioBomRoot,
00092                     stdair::Inventory& ioInventory,
00093                     const stdair::Date_T& iFlightDate,
00094                     const FlightPeriodStruct& iFlightPeriod) {
00095     // Create the FlightDateKey
00096     const stdair::FlightNumber_T& lFlightNumber = iFlightPeriod._flightNumber;
00097     stdair::FlightDateKey lFlightDateKey (lFlightNumber, iFlightDate);
00098 
00099     // DEBUG
00100     // STDAIR_LOG_DEBUG ("Creating flight-date: " << lFlightDateKey.toString());
00101     
00102     // Check that the flight-date object is not already existing. If a
00103     // FlightDate object with the same key has already been created,
00104     // it means that the schedule input file is invalid (two flight-periods
00105     // are overlapping).
00106     stdair::FlightDate* lFlightDate_ptr = stdair::BomManager::
00107       getObjectPtr<stdair::FlightDate> (ioInventory, lFlightDateKey.toString());
00108     if (lFlightDate_ptr != NULL) {
00109       std::ostringstream oMessage;
00110       oMessage << ioInventory.describeKey() << ", "
00111                << lFlightDate_ptr->describeKey();
00112       throw FlightDateDuplicationException (oMessage.str());
00113     }
00114 
00115     // Instantiate a fligh-date object with the given key (flight number and
00116     // flight date)
00117     lFlightDate_ptr =
00118       &stdair::FacBom<stdair::FlightDate>::instance().create (lFlightDateKey);
00119     stdair::FacBomManager::addToListAndMap (ioInventory, *lFlightDate_ptr);
00120     stdair::FacBomManager::linkWithParent (ioInventory, *lFlightDate_ptr);
00121       
00122     // Iterate on the leg-dates
00123     stdair::Duration_T currentOffTime (0, 0, 0);
00124     stdair::AirportCode_T previousOffPoint;
00125     const LegStructList_T& lLegList = iFlightPeriod._legList;
00126     for (LegStructList_T::const_iterator itLeg = lLegList.begin();
00127          itLeg != lLegList.end(); ++itLeg) {
00128       const LegStruct& lLeg = *itLeg;
00129 
00130       // Create the leg-branch of the flight-date BOM
00131       stdair::LegDate& lLegDate =
00132         createLegDate (*lFlightDate_ptr, iFlightDate, lLeg);
00133 
00134       // TODO: Check that the boarding date/time of the next leg is greated
00135       // than the off date/time of the current leg. Throw an exception
00136       // otherwise.
00137 
00138       // TODO: specify, in the schedule input file specifications, that the
00139       // legs should be given in their natural order.
00140       // Then, replace the assertion by a thrown exception.
00141       //
00142       // Check that the legs are given in their natural order. If the schedule
00143       // input does not respect that assumption, the following assertion will
00144       // fail.
00145       if (itLeg != lLegList.begin()) {
00146         const stdair::AirportCode_T& currentBoardingPoint =
00147           lLegDate.getBoardingPoint();
00148         assert (currentBoardingPoint == previousOffPoint);
00149       }
00150         
00151       // Set the local variable for the next iteration
00152       previousOffPoint = lLegDate.getOffPoint();
00153     }
00154 
00155     // Iterate on the segment structures
00156     const SegmentStructList_T& lSegmentList = iFlightPeriod._segmentList;
00157     for (SegmentStructList_T::const_iterator itSegment = lSegmentList.begin();
00158          itSegment != lSegmentList.end(); ++itSegment) {
00159       const SegmentStruct& lSegment = *itSegment;
00160 
00161       createSegmentDate (ioBomRoot, *lFlightDate_ptr, lSegment);
00162     }
00163 
00164     createRoutingLegKey (*lFlightDate_ptr);
00165   }  
00166 
00167   // ////////////////////////////////////////////////////////////////////
00168   void InventoryGenerator::
00169   createRoutingLegKey (stdair::FlightDate& ioFlightDate) {
00170 
00171     // Browse the list of segment-dates and create direct accesses
00172     // within each segment-date.
00173     const stdair::SegmentDateList_T& lSegmentDateList = 
00174       stdair::BomManager::getList<stdair::SegmentDate> (ioFlightDate);
00175     for (stdair::SegmentDateList_T::const_iterator itSegmentDate = 
00176            lSegmentDateList.begin();
00177          itSegmentDate != lSegmentDateList.end(); ++itSegmentDate) {
00178 
00179       stdair::SegmentDate* lCurrentSegmentDate_ptr = *itSegmentDate;
00180       assert (lCurrentSegmentDate_ptr != NULL);
00181 
00182       const stdair::AirportCode_T& lBoardingPoint =
00183         lCurrentSegmentDate_ptr->getBoardingPoint();
00184         
00185       stdair::AirportCode_T currentBoardingPoint = lBoardingPoint;
00186       const stdair::AirportCode_T& lOffPoint =
00187         lCurrentSegmentDate_ptr->getOffPoint();
00188         
00189       // Add a sanity check so as to ensure that the loop stops. If
00190       // there are more than MAXIMAL_NUMBER_OF_LEGS legs, there is
00191       // an issue somewhere in the code (not in the parser, as the
00192       // segments are derived from the legs thanks to the
00193       // FlightPeriodStruct::buildSegments() method).
00194       unsigned short i = 1;
00195       while (currentBoardingPoint != lOffPoint
00196              && i <= stdair::MAXIMAL_NUMBER_OF_LEGS_IN_FLIGHT) {
00197         // Retrieve the (unique) LegDate getting that Boarding Point
00198         stdair::LegDate& lLegDate = stdair::BomManager::
00199           getObject<stdair::LegDate> (ioFlightDate, currentBoardingPoint);
00200         
00201         // Link the SegmentDate and LegDate together
00202         const std::string& lRoutingKeyStr = lLegDate.describeRoutingKey();
00203         lCurrentSegmentDate_ptr->addLegKey(lRoutingKeyStr);
00204           
00205         // Prepare the next iteration
00206         currentBoardingPoint = lLegDate.getOffPoint();
00207         ++i;
00208       }
00209       assert (i <= stdair::MAXIMAL_NUMBER_OF_LEGS_IN_FLIGHT);
00210     }
00211   }
00212 
00213   // ////////////////////////////////////////////////////////////////////
00214   stdair::LegDate& InventoryGenerator::
00215   createLegDate (stdair::FlightDate& ioFlightDate,
00216                  const stdair::Date_T& iReferenceDate,
00217                  const LegStruct& iLeg) {
00218     // Create the leg-date corresponding to the boarding point.
00219     stdair::LegDateKey lKey (iLeg._boardingPoint);
00220     stdair::LegDate& lLegDate =
00221       stdair::FacBom<stdair::LegDate>::instance().create (lKey);
00222     stdair::FacBomManager::addToListAndMap (ioFlightDate, lLegDate);
00223     stdair::FacBomManager::linkWithParent (ioFlightDate, lLegDate);
00224 
00225     // Set the leg-date attributes
00226     iLeg.fill (iReferenceDate, lLegDate);
00227     
00228     // Iterate on the cabins
00229     const LegCabinStructList_T& lCabinList = iLeg._cabinList;
00230     for (LegCabinStructList_T::const_iterator itCabin = lCabinList.begin();
00231          itCabin != lCabinList.end(); ++itCabin) {
00232       const LegCabinStruct& lCabin = *itCabin;
00233 
00234       // Create the leg-cabin-branch of the leg-date 
00235       createLegCabin (lLegDate, lCabin);
00236     }
00237 
00238     return lLegDate;
00239   }
00240 
00241   // ////////////////////////////////////////////////////////////////////
00242   void InventoryGenerator::
00243   createLegCabin (stdair::LegDate& ioLegDate,
00244                   const LegCabinStruct& iCabin) {
00245     // Instantiate an leg-cabin object with the corresponding cabin code
00246     const stdair::LegCabinKey lKey (iCabin._cabinCode);
00247     stdair::LegCabin& lLegCabin =
00248       stdair::FacBom<stdair::LegCabin>::instance().create (lKey);
00249     stdair::FacBomManager::addToListAndMap (ioLegDate, lLegCabin);
00250     stdair::FacBomManager::linkWithParent (ioLegDate, lLegCabin);
00251 
00252     // Set the Leg-Cabin attributes
00253     iCabin.fill (lLegCabin);
00254 
00255     // Iterate on the bucket
00256     const BucketStructList_T& lBucketList = iCabin._bucketList;
00257     for (BucketStructList_T::const_iterator itBucket = lBucketList.begin();
00258          itBucket != lBucketList.end(); ++itBucket) {
00259       const BucketStruct& lBucket = *itBucket;
00260 
00261       // Create the bucket of the leg-cabin
00262       createBucket (lLegCabin, lBucket);
00263     }
00264   }
00265     
00266   // ////////////////////////////////////////////////////////////////////
00267   void InventoryGenerator::createBucket (stdair::LegCabin& ioLegCabin,
00268                                          const BucketStruct& iBucket) {
00269     // Instantiate a bucket object with the corresponding seat index
00270     const stdair::BucketKey lKey (iBucket._seatIndex);
00271     stdair::Bucket& lBucket =
00272       stdair::FacBom<stdair::Bucket>::instance().create (lKey);
00273     stdair::FacBomManager::addToListAndMap (ioLegCabin, lBucket);
00274     stdair::FacBomManager::linkWithParent (ioLegCabin, lBucket);
00275 
00276     // Set the Bucket attributes
00277     iBucket.fill (lBucket);
00278   }
00279 
00280   // ////////////////////////////////////////////////////////////////////
00281   void InventoryGenerator::
00282   createSegmentDate (stdair::BomRoot& ioBomRoot,
00283                      stdair::FlightDate& ioFlightDate,
00284                      const SegmentStruct& iSegment) {
00285     // Set the segment-date primary key
00286     const stdair::AirportCode_T& lBoardingPoint = iSegment._boardingPoint;
00287     const stdair::AirportCode_T& lOffPoint = iSegment._offPoint;
00288     stdair::SegmentDateKey lSegmentDateKey (lBoardingPoint, lOffPoint);
00289     // Instantiate an segment-date object with the key.
00290     stdair::SegmentDate& lSegmentDate =
00291       stdair::FacBom<stdair::SegmentDate>::instance().create (lSegmentDateKey);
00292     stdair::FacBomManager::addToListAndMap (ioFlightDate, lSegmentDate);
00293     stdair::FacBomManager::linkWithParent (ioFlightDate, lSegmentDate);
00294     
00295     // Set the segment-date attributes
00296     iSegment.fill (lSegmentDate);
00297       
00298     // Iterate on the Cabins
00299     const SegmentCabinStructList_T& lCabinList = iSegment._cabinList;
00300     for (SegmentCabinStructList_T::const_iterator itCabin =
00301            lCabinList.begin(); itCabin != lCabinList.end(); ++itCabin) {
00302       const SegmentCabinStruct& lCabin = *itCabin;
00303 
00304       // Create the segment-cabin-branch of the segment-date BOM
00305       createSegmentCabin (ioBomRoot, lSegmentDate, lCabin);
00306     }
00307   }
00308     
00309   // ////////////////////////////////////////////////////////////////////
00310   void InventoryGenerator::
00311   createSegmentCabin (stdair::BomRoot& ioBomRoot,
00312                       stdair::SegmentDate& ioSegmentDate,
00313                       const SegmentCabinStruct& iCabin) {
00314 
00315     // Instantiate an segment-cabin object with the corresponding cabin code
00316     stdair::SegmentCabinKey lKey (iCabin._cabinCode);
00317     stdair::SegmentCabin& lSegmentCabin =
00318       stdair::FacBom<stdair::SegmentCabin>::instance().create (lKey);
00319 
00320     // Link the segment-cabin to its parent, the segment-date
00321     stdair::FacBomManager::addToListAndMap (ioSegmentDate, lSegmentCabin);
00322     stdair::FacBomManager::linkWithParent (ioSegmentDate, lSegmentCabin);
00323     
00324     // Set the segment-cabin attributes
00325     iCabin.fill (lSegmentCabin);
00326 
00327     // Create the list of fare families        
00328     for (FareFamilyStructList_T::const_iterator itFareFamily =
00329            iCabin._fareFamilies.begin();
00330          itFareFamily != iCabin._fareFamilies.end(); itFareFamily++) {
00331       const FareFamilyStruct& lFareFamilyStruct = *itFareFamily;
00332 
00333       // Create the fare families and the booking classes.
00334       createFareFamily (ioBomRoot, lSegmentCabin, lFareFamilyStruct);
00335     } 
00336 
00337     const unsigned int lNbOfFareFamilies = iCabin._fareFamilies.size();
00338     if (lNbOfFareFamilies > 1) {
00339       lSegmentCabin.activateFareFamily();
00340     } 
00341 
00342     // Create the display nesting structure.
00343     createDisplayNestingStructure (lSegmentCabin);
00344   }
00345     
00346   // ////////////////////////////////////////////////////////////////////
00347   void InventoryGenerator::
00348   createFareFamily (stdair::BomRoot& ioBomRoot,
00349                     stdair::SegmentCabin& ioSegmentCabin,
00350                     const FareFamilyStruct& iFF) {
00351     // Instantiate an segment-cabin object with the corresponding cabin code
00352     stdair::FareFamilyKey lKey (iFF._familyCode);
00353     stdair::FareFamily& lFareFamily =
00354       stdair::FacBom<stdair::FareFamily>::instance().create (lKey);
00355 
00356     // Link the fare family to its parent, the segment-cabin
00357     stdair::FacBomManager::addToListAndMap (ioSegmentCabin, lFareFamily);
00358     stdair::FacBomManager::linkWithParent (ioSegmentCabin, lFareFamily);
00359     
00360     // Set the fare family attributes
00361     iFF.fill (lFareFamily);
00362     const stdair::FRAT5Curve_T& lFRAT5Curve =
00363       ioBomRoot.getFRAT5Curve (iFF._frat5CurveKey);
00364     lFareFamily.setFrat5Curve (lFRAT5Curve);
00365     const stdair::FFDisutilityCurve_T& lDisutilityCurve =
00366       ioBomRoot.getFFDisutilityCurve (iFF._ffDisutilityCurveKey);
00367     lFareFamily.setDisutilityCurve (lDisutilityCurve);
00368 
00369     // Iterate on the classes
00370     const stdair::ClassList_String_T& lClassList = iFF._classes;
00371     for (stdair::ClassList_String_T::const_iterator itClass =
00372            lClassList.begin(); itClass != lClassList.end(); ++itClass) {
00373       // Transform the single-character class code into a STL string
00374       std::ostringstream ostr;
00375       ostr << *itClass;
00376       const stdair::ClassCode_T lClassCode (ostr.str());
00377       
00378       // Create the booking class branch of the segment-cabin BOM
00379       createClass (lFareFamily, lClassCode);
00380     }
00381   }
00382 
00383   // ////////////////////////////////////////////////////////////////////
00384   void InventoryGenerator::createClass (stdair::FareFamily& ioFareFamily,
00385                                         const stdair::ClassCode_T& iClassCode) {
00386 
00387     // Instantiate a booking class object with the given class code
00388     const stdair::BookingClassKey lClassKey (iClassCode);
00389     stdair::BookingClass& lClass =
00390       stdair::FacBom<stdair::BookingClass>::instance().create (lClassKey);
00391 
00392     // Link the booking-class to the fare family
00393     stdair::FacBomManager::addToListAndMap (ioFareFamily, lClass);
00394     stdair::FacBomManager::linkWithParent (ioFareFamily, lClass);
00395 
00396     // Link the booking-class to the segment-cabin
00397     stdair::SegmentCabin& lSegmentCabin =
00398       stdair::BomManager::getParent<stdair::SegmentCabin> (ioFareFamily);
00399     stdair::FacBomManager::addToListAndMap (lSegmentCabin, lClass);
00400 
00401     // Link the booking-class to the segment-date
00402     stdair::SegmentDate& lSegmentDate =
00403       stdair::BomManager::getParent<stdair::SegmentDate> (lSegmentCabin);
00404     stdair::FacBomManager::addToListAndMap (lSegmentDate, lClass);
00405   }
00406     
00407   // ////////////////////////////////////////////////////////////////////
00408   void InventoryGenerator::
00409   createDisplayNestingStructure (stdair::SegmentCabin& ioSegmentCabin) {
00410     // Create the nesting structure.
00411     stdair::NestingStructureKey lKey (stdair::DISPLAY_NESTING_STRUCTURE_CODE);
00412     stdair::SimpleNestingStructure& lNestingStructure =
00413       stdair::FacBom<stdair::SimpleNestingStructure>::instance().create(lKey);
00414     stdair::FacBomManager::addToListAndMap (ioSegmentCabin, lNestingStructure);
00415     stdair::FacBomManager::linkWithParent (ioSegmentCabin, lNestingStructure);
00416     
00417     // Browse the list of booking classes and create the nesting structure
00418     // based on that list. Each nesting node consists of a booking class.
00419     const stdair::BookingClassList_T& lBCList =
00420       stdair::BomManager::getList<stdair::BookingClass>(ioSegmentCabin);
00421     for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
00422          itBC != lBCList.end(); ++itBC) {
00423       stdair::BookingClass* lBC_ptr = *itBC;
00424       assert (lBC_ptr != NULL);
00425 
00426       // Create a nesting node
00427       stdair::NestingNodeCode_T lNodeCode (lBC_ptr->describeKey());
00428       stdair::NestingNodeKey lNodeKey (lNodeCode);
00429       stdair::NestingNode& lNestingNode =
00430         stdair::FacBom<stdair::NestingNode>::instance().create (lNodeKey);
00431       stdair::FacBomManager::addToList (lNestingStructure, lNestingNode);
00432       stdair::FacBomManager::linkWithParent (lNestingStructure, lNestingNode);
00433 
00434       // Add the booking class to the node.
00435       stdair::FacBomManager::addToList (lNestingNode, *lBC_ptr);
00436     }
00437   }
00438 }