AirInv Logo  1.00.0
C++ Simulated Airline Inventory Management System library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
InventoryGenerator.cpp
Go to the documentation of this file.
1 // //////////////////////////////////////////////////////////////////////
2 // Import section
3 // //////////////////////////////////////////////////////////////////////
4 // STL
5 #include <cassert>
6 // Boost
7 #include <boost/date_time/date_iterator.hpp>
8 // StdAir
9 #include <stdair/stdair_types.hpp>
10 #include <stdair/basic/BasConst_Inventory.hpp>
11 #include <stdair/basic/BasConst_SellUpCurves.hpp>
12 #include <stdair/bom/BomManager.hpp>
13 #include <stdair/bom/BomRoot.hpp>
14 #include <stdair/bom/Inventory.hpp>
15 #include <stdair/bom/AirlineFeature.hpp>
16 #include <stdair/bom/FlightDate.hpp>
17 #include <stdair/bom/SegmentDate.hpp>
18 #include <stdair/bom/SegmentCabin.hpp>
19 #include <stdair/bom/FareFamily.hpp>
20 #include <stdair/bom/BookingClass.hpp>
21 #include <stdair/bom/LegDate.hpp>
22 #include <stdair/bom/LegCabin.hpp>
23 #include <stdair/bom/SimpleNestingStructure.hpp>
24 #include <stdair/bom/NestingNode.hpp>
25 #include <stdair/bom/Policy.hpp>
26 #include <stdair/bom/Bucket.hpp>
27 #include <stdair/bom/BomKeyManager.hpp>
28 #include <stdair/factory/FacBomManager.hpp>
29 #include <stdair/service/Logger.hpp>
30 // AirInv
33 
34 namespace AIRINV {
35 
36  // ////////////////////////////////////////////////////////////////////
37  void InventoryGenerator::
38  createFlightDate (stdair::BomRoot& ioBomRoot,
39  const FlightPeriodStruct& iFlightPeriod) {
40  const stdair::AirlineCode_T& lAirlineCode = iFlightPeriod._airlineCode;
41 
42  // Instantiate an inventory object (if not exist)
43  // for the given key (airline code)
44  stdair::Inventory* lInventory_ptr = stdair::BomManager::
45  getObjectPtr<stdair::Inventory> (ioBomRoot, lAirlineCode);
46  if (lInventory_ptr == NULL) {
47  stdair::InventoryKey lKey (lAirlineCode);
48  lInventory_ptr =
49  &stdair::FacBom<stdair::Inventory>::instance().create (lKey);
50  stdair::FacBomManager::addToListAndMap (ioBomRoot, *lInventory_ptr);
51  stdair::FacBomManager::linkWithParent (ioBomRoot, *lInventory_ptr);
52 
53  // Add the airline feature object to the inventory
54  const stdair::AirlineFeatureKey lAirlineFeatureKey (lAirlineCode);
55  stdair::AirlineFeature& lAirlineFeature =
56  stdair::FacBom<stdair::AirlineFeature>::instance().create (lAirlineFeatureKey);
57  stdair::FacBomManager::setAirlineFeature (*lInventory_ptr,
58  lAirlineFeature);
59  stdair::FacBomManager::linkWithParent (*lInventory_ptr, lAirlineFeature);
60  // Link the airline feature object with the top of the BOM tree
61  stdair::FacBomManager::addToListAndMap (ioBomRoot, lAirlineFeature);
62  }
63  assert (lInventory_ptr != NULL);
64 
65  // Generate all the dates corresponding to the period
66  // and create the corresponding flight-dates.
67  const stdair::DatePeriod_T lDateRange = iFlightPeriod._dateRange;
68 
69  for (boost::gregorian::day_iterator itDate = lDateRange.begin();
70  itDate != lDateRange.end(); ++itDate) {
71  const stdair::Date_T& currentDate = *itDate;
72 
73  // Retrieve, for the current day, the Day-Of-the-Week (thanks to Boost)
74  const unsigned short currentDoW = currentDate.day_of_week().as_number();
75 
76  // The FlightPeriod structure stores which Days (-Of-the-Week) are
77  // active within the week. For each day (Mon., Tue., etc.), a boolean
78  // states whether the Flight is active for that day.
79  const stdair::DoWStruct& lDoWList = iFlightPeriod._dow;
80  const bool isDoWActive = lDoWList.getStandardDayOfWeek (currentDoW);
81 
82  if (isDoWActive == true) {
83  createFlightDate (ioBomRoot, *lInventory_ptr, currentDate,
84  iFlightPeriod);
85  }
86  }
87  }
88 
89  // ////////////////////////////////////////////////////////////////////
90  void InventoryGenerator::
91  createFlightDate (stdair::BomRoot& ioBomRoot,
92  stdair::Inventory& ioInventory,
93  const stdair::Date_T& iFlightDate,
94  const FlightPeriodStruct& iFlightPeriod) {
95  // Create the FlightDateKey
96  const stdair::FlightNumber_T& lFlightNumber = iFlightPeriod._flightNumber;
97  stdair::FlightDateKey lFlightDateKey (lFlightNumber, iFlightDate);
98 
99  // DEBUG
100  // STDAIR_LOG_DEBUG ("Creating flight-date: " << lFlightDateKey.toString());
101 
102  // Check that the flight-date object is not already existing. If a
103  // FlightDate object with the same key has already been created,
104  // it means that the schedule input file is invalid (two flight-periods
105  // are overlapping).
106  stdair::FlightDate* lFlightDate_ptr = stdair::BomManager::
107  getObjectPtr<stdair::FlightDate> (ioInventory, lFlightDateKey.toString());
108  if (lFlightDate_ptr != NULL) {
109  std::ostringstream oMessage;
110  oMessage << ioInventory.describeKey() << ", "
111  << lFlightDate_ptr->describeKey();
112  throw FlightDateDuplicationException (oMessage.str());
113  }
114 
115  // Instantiate a fligh-date object with the given key (flight number and
116  // flight date)
117  lFlightDate_ptr =
118  &stdair::FacBom<stdair::FlightDate>::instance().create (lFlightDateKey);
119  stdair::FacBomManager::addToListAndMap (ioInventory, *lFlightDate_ptr);
120  stdair::FacBomManager::linkWithParent (ioInventory, *lFlightDate_ptr);
121 
122  // Iterate on the leg-dates
123  stdair::Duration_T currentOffTime (0, 0, 0);
124  stdair::AirportCode_T previousOffPoint;
125  const LegStructList_T& lLegList = iFlightPeriod._legList;
126  for (LegStructList_T::const_iterator itLeg = lLegList.begin();
127  itLeg != lLegList.end(); ++itLeg) {
128  const LegStruct& lLeg = *itLeg;
129 
130  // Create the leg-branch of the flight-date BOM
131  stdair::LegDate& lLegDate =
132  createLegDate (*lFlightDate_ptr, iFlightDate, lLeg);
133 
134  // TODO: Check that the boarding date/time of the next leg is greated
135  // than the off date/time of the current leg. Throw an exception
136  // otherwise.
137 
138  // TODO: specify, in the schedule input file specifications, that the
139  // legs should be given in their natural order.
140  // Then, replace the assertion by a thrown exception.
141  //
142  // Check that the legs are given in their natural order. If the schedule
143  // input does not respect that assumption, the following assertion will
144  // fail.
145  if (itLeg != lLegList.begin()) {
146  const stdair::AirportCode_T& currentBoardingPoint =
147  lLegDate.getBoardingPoint();
148  assert (currentBoardingPoint == previousOffPoint);
149  }
150 
151  // Set the local variable for the next iteration
152  previousOffPoint = lLegDate.getOffPoint();
153  }
154 
155  // Iterate on the segment structures
156  const SegmentStructList_T& lSegmentList = iFlightPeriod._segmentList;
157  for (SegmentStructList_T::const_iterator itSegment = lSegmentList.begin();
158  itSegment != lSegmentList.end(); ++itSegment) {
159  const SegmentStruct& lSegment = *itSegment;
160 
161  createSegmentDate (ioBomRoot, *lFlightDate_ptr, lSegment);
162  }
163 
164  createRoutingLegKey (*lFlightDate_ptr);
165  }
166 
167  // ////////////////////////////////////////////////////////////////////
168  void InventoryGenerator::
169  createRoutingLegKey (stdair::FlightDate& ioFlightDate) {
170 
171  // Browse the list of segment-dates and create direct accesses
172  // within each segment-date.
173  const stdair::SegmentDateList_T& lSegmentDateList =
174  stdair::BomManager::getList<stdair::SegmentDate> (ioFlightDate);
175  for (stdair::SegmentDateList_T::const_iterator itSegmentDate =
176  lSegmentDateList.begin();
177  itSegmentDate != lSegmentDateList.end(); ++itSegmentDate) {
178 
179  stdair::SegmentDate* lCurrentSegmentDate_ptr = *itSegmentDate;
180  assert (lCurrentSegmentDate_ptr != NULL);
181 
182  const stdair::AirportCode_T& lBoardingPoint =
183  lCurrentSegmentDate_ptr->getBoardingPoint();
184 
185  stdair::AirportCode_T currentBoardingPoint = lBoardingPoint;
186  const stdair::AirportCode_T& lOffPoint =
187  lCurrentSegmentDate_ptr->getOffPoint();
188 
189  // Add a sanity check so as to ensure that the loop stops. If
190  // there are more than MAXIMAL_NUMBER_OF_LEGS legs, there is
191  // an issue somewhere in the code (not in the parser, as the
192  // segments are derived from the legs thanks to the
193  // FlightPeriodStruct::buildSegments() method).
194  unsigned short i = 1;
195  while (currentBoardingPoint != lOffPoint
196  && i <= stdair::MAXIMAL_NUMBER_OF_LEGS_IN_FLIGHT) {
197  // Retrieve the (unique) LegDate getting that Boarding Point
198  stdair::LegDate& lLegDate = stdair::BomManager::
199  getObject<stdair::LegDate> (ioFlightDate, currentBoardingPoint);
200 
201  // Link the SegmentDate and LegDate together
202  const std::string& lRoutingKeyStr = lLegDate.describeRoutingKey();
203  lCurrentSegmentDate_ptr->addLegKey(lRoutingKeyStr);
204 
205  // Prepare the next iteration
206  currentBoardingPoint = lLegDate.getOffPoint();
207  ++i;
208  }
209  assert (i <= stdair::MAXIMAL_NUMBER_OF_LEGS_IN_FLIGHT);
210  }
211  }
212 
213  // ////////////////////////////////////////////////////////////////////
214  stdair::LegDate& InventoryGenerator::
215  createLegDate (stdair::FlightDate& ioFlightDate,
216  const stdair::Date_T& iReferenceDate,
217  const LegStruct& iLeg) {
218  // Create the leg-date corresponding to the boarding point.
219  stdair::LegDateKey lKey (iLeg._boardingPoint);
220  stdair::LegDate& lLegDate =
221  stdair::FacBom<stdair::LegDate>::instance().create (lKey);
222  stdair::FacBomManager::addToListAndMap (ioFlightDate, lLegDate);
223  stdair::FacBomManager::linkWithParent (ioFlightDate, lLegDate);
224 
225  // Set the leg-date attributes
226  iLeg.fill (iReferenceDate, lLegDate);
227 
228  // Iterate on the cabins
229  const LegCabinStructList_T& lCabinList = iLeg._cabinList;
230  for (LegCabinStructList_T::const_iterator itCabin = lCabinList.begin();
231  itCabin != lCabinList.end(); ++itCabin) {
232  const LegCabinStruct& lCabin = *itCabin;
233 
234  // Create the leg-cabin-branch of the leg-date
235  createLegCabin (lLegDate, lCabin);
236  }
237 
238  return lLegDate;
239  }
240 
241  // ////////////////////////////////////////////////////////////////////
242  void InventoryGenerator::
243  createLegCabin (stdair::LegDate& ioLegDate,
244  const LegCabinStruct& iCabin) {
245  // Instantiate an leg-cabin object with the corresponding cabin code
246  const stdair::LegCabinKey lKey (iCabin._cabinCode);
247  stdair::LegCabin& lLegCabin =
248  stdair::FacBom<stdair::LegCabin>::instance().create (lKey);
249  stdair::FacBomManager::addToListAndMap (ioLegDate, lLegCabin);
250  stdair::FacBomManager::linkWithParent (ioLegDate, lLegCabin);
251 
252  // Set the Leg-Cabin attributes
253  iCabin.fill (lLegCabin);
254 
255  // Iterate on the bucket
256  const BucketStructList_T& lBucketList = iCabin._bucketList;
257  for (BucketStructList_T::const_iterator itBucket = lBucketList.begin();
258  itBucket != lBucketList.end(); ++itBucket) {
259  const BucketStruct& lBucket = *itBucket;
260 
261  // Create the bucket of the leg-cabin
262  createBucket (lLegCabin, lBucket);
263  }
264  }
265 
266  // ////////////////////////////////////////////////////////////////////
267  void InventoryGenerator::createBucket (stdair::LegCabin& ioLegCabin,
268  const BucketStruct& iBucket) {
269  // Instantiate a bucket object with the corresponding seat index
270  const stdair::BucketKey lKey (iBucket._seatIndex);
271  stdair::Bucket& lBucket =
272  stdair::FacBom<stdair::Bucket>::instance().create (lKey);
273  stdair::FacBomManager::addToListAndMap (ioLegCabin, lBucket);
274  stdair::FacBomManager::linkWithParent (ioLegCabin, lBucket);
275 
276  // Set the Bucket attributes
277  iBucket.fill (lBucket);
278  }
279 
280  // ////////////////////////////////////////////////////////////////////
281  void InventoryGenerator::
282  createSegmentDate (stdair::BomRoot& ioBomRoot,
283  stdair::FlightDate& ioFlightDate,
284  const SegmentStruct& iSegment) {
285  // Set the segment-date primary key
286  const stdair::AirportCode_T& lBoardingPoint = iSegment._boardingPoint;
287  const stdair::AirportCode_T& lOffPoint = iSegment._offPoint;
288  stdair::SegmentDateKey lSegmentDateKey (lBoardingPoint, lOffPoint);
289  // Instantiate an segment-date object with the key.
290  stdair::SegmentDate& lSegmentDate =
291  stdair::FacBom<stdair::SegmentDate>::instance().create (lSegmentDateKey);
292  stdair::FacBomManager::addToListAndMap (ioFlightDate, lSegmentDate);
293  stdair::FacBomManager::linkWithParent (ioFlightDate, lSegmentDate);
294 
295  // Set the segment-date attributes
296  iSegment.fill (lSegmentDate);
297 
298  // Iterate on the Cabins
299  const SegmentCabinStructList_T& lCabinList = iSegment._cabinList;
300  for (SegmentCabinStructList_T::const_iterator itCabin =
301  lCabinList.begin(); itCabin != lCabinList.end(); ++itCabin) {
302  const SegmentCabinStruct& lCabin = *itCabin;
303 
304  // Create the segment-cabin-branch of the segment-date BOM
305  createSegmentCabin (ioBomRoot, lSegmentDate, lCabin);
306  }
307  }
308 
309  // ////////////////////////////////////////////////////////////////////
310  void InventoryGenerator::
311  createSegmentCabin (stdair::BomRoot& ioBomRoot,
312  stdair::SegmentDate& ioSegmentDate,
313  const SegmentCabinStruct& iCabin) {
314 
315  // Instantiate an segment-cabin object with the corresponding cabin code
316  stdair::SegmentCabinKey lKey (iCabin._cabinCode);
317  stdair::SegmentCabin& lSegmentCabin =
318  stdair::FacBom<stdair::SegmentCabin>::instance().create (lKey);
319 
320  // Link the segment-cabin to its parent, the segment-date
321  stdair::FacBomManager::addToListAndMap (ioSegmentDate, lSegmentCabin);
322  stdair::FacBomManager::linkWithParent (ioSegmentDate, lSegmentCabin);
323 
324  // Set the segment-cabin attributes
325  iCabin.fill (lSegmentCabin);
326 
327  // Create the list of fare families
328  for (FareFamilyStructList_T::const_iterator itFareFamily =
329  iCabin._fareFamilies.begin();
330  itFareFamily != iCabin._fareFamilies.end(); itFareFamily++) {
331  const FareFamilyStruct& lFareFamilyStruct = *itFareFamily;
332 
333  // Create the fare families and the booking classes.
334  createFareFamily (ioBomRoot, lSegmentCabin, lFareFamilyStruct);
335  }
336 
337  const unsigned int lNbOfFareFamilies = iCabin._fareFamilies.size();
338  if (lNbOfFareFamilies > 1) {
339  lSegmentCabin.activateFareFamily();
340  }
341 
342  // Create the display nesting structure.
343  createDisplayNestingStructure (lSegmentCabin);
344  }
345 
346  // ////////////////////////////////////////////////////////////////////
347  void InventoryGenerator::
348  createFareFamily (stdair::BomRoot& ioBomRoot,
349  stdair::SegmentCabin& ioSegmentCabin,
350  const FareFamilyStruct& iFF) {
351  // Instantiate an segment-cabin object with the corresponding cabin code
352  stdair::FareFamilyKey lKey (iFF._familyCode);
353  stdair::FareFamily& lFareFamily =
354  stdair::FacBom<stdair::FareFamily>::instance().create (lKey);
355 
356  // Link the fare family to its parent, the segment-cabin
357  stdair::FacBomManager::addToListAndMap (ioSegmentCabin, lFareFamily);
358  stdair::FacBomManager::linkWithParent (ioSegmentCabin, lFareFamily);
359 
360  // Set the fare family attributes
361  iFF.fill (lFareFamily);
362  const stdair::FRAT5Curve_T& lFRAT5Curve =
363  ioBomRoot.getFRAT5Curve (iFF._frat5CurveKey);
364  lFareFamily.setFrat5Curve (lFRAT5Curve);
365  const stdair::FFDisutilityCurve_T& lDisutilityCurve =
366  ioBomRoot.getFFDisutilityCurve (iFF._ffDisutilityCurveKey);
367  lFareFamily.setDisutilityCurve (lDisutilityCurve);
368 
369  // Iterate on the classes
370  const stdair::ClassList_String_T& lClassList = iFF._classes;
371  for (stdair::ClassList_String_T::const_iterator itClass =
372  lClassList.begin(); itClass != lClassList.end(); ++itClass) {
373  // Transform the single-character class code into a STL string
374  std::ostringstream ostr;
375  ostr << *itClass;
376  const stdair::ClassCode_T lClassCode (ostr.str());
377 
378  // Create the booking class branch of the segment-cabin BOM
379  createClass (lFareFamily, lClassCode);
380  }
381  }
382 
383  // ////////////////////////////////////////////////////////////////////
384  void InventoryGenerator::createClass (stdair::FareFamily& ioFareFamily,
385  const stdair::ClassCode_T& iClassCode) {
386 
387  // Instantiate a booking class object with the given class code
388  const stdair::BookingClassKey lClassKey (iClassCode);
389  stdair::BookingClass& lClass =
390  stdair::FacBom<stdair::BookingClass>::instance().create (lClassKey);
391 
392  // Link the booking-class to the fare family
393  stdair::FacBomManager::addToListAndMap (ioFareFamily, lClass);
394  stdair::FacBomManager::linkWithParent (ioFareFamily, lClass);
395 
396  // Link the booking-class to the segment-cabin
397  stdair::SegmentCabin& lSegmentCabin =
398  stdair::BomManager::getParent<stdair::SegmentCabin> (ioFareFamily);
399  stdair::FacBomManager::addToListAndMap (lSegmentCabin, lClass);
400 
401  // Link the booking-class to the segment-date
402  stdair::SegmentDate& lSegmentDate =
403  stdair::BomManager::getParent<stdair::SegmentDate> (lSegmentCabin);
404  stdair::FacBomManager::addToListAndMap (lSegmentDate, lClass);
405  }
406 
407  // ////////////////////////////////////////////////////////////////////
408  void InventoryGenerator::
409  createDisplayNestingStructure (stdair::SegmentCabin& ioSegmentCabin) {
410  // Create the nesting structure.
411  stdair::NestingStructureKey lKey (stdair::DISPLAY_NESTING_STRUCTURE_CODE);
412  stdair::SimpleNestingStructure& lNestingStructure =
413  stdair::FacBom<stdair::SimpleNestingStructure>::instance().create(lKey);
414  stdair::FacBomManager::addToListAndMap (ioSegmentCabin, lNestingStructure);
415  stdair::FacBomManager::linkWithParent (ioSegmentCabin, lNestingStructure);
416 
417  // Browse the list of booking classes and create the nesting structure
418  // based on that list. Each nesting node consists of a booking class.
419  const stdair::BookingClassList_T& lBCList =
420  stdair::BomManager::getList<stdair::BookingClass>(ioSegmentCabin);
421  for (stdair::BookingClassList_T::const_iterator itBC = lBCList.begin();
422  itBC != lBCList.end(); ++itBC) {
423  stdair::BookingClass* lBC_ptr = *itBC;
424  assert (lBC_ptr != NULL);
425 
426  // Create a nesting node
427  stdair::NestingNodeCode_T lNodeCode (lBC_ptr->describeKey());
428  stdair::NestingNodeKey lNodeKey (lNodeCode);
429  stdair::NestingNode& lNestingNode =
430  stdair::FacBom<stdair::NestingNode>::instance().create (lNodeKey);
431  stdair::FacBomManager::addToList (lNestingStructure, lNestingNode);
432  stdair::FacBomManager::linkWithParent (lNestingStructure, lNestingNode);
433 
434  // Add the booking class to the node.
435  stdair::FacBomManager::addToList (lNestingNode, *lBC_ptr);
436  }
437  }
438 }