StdAir Logo  0.44.0
C++ Standard Airline IT Object Library
FacBomManager.hpp
Go to the documentation of this file.
00001 #ifndef __STDAIR_FAC_FACBOMMANAGER_HPP
00002 #define __STDAIR_FAC_FACBOMMANAGER_HPP
00003 
00004 // //////////////////////////////////////////////////////////////////////
00005 // Import section
00006 // //////////////////////////////////////////////////////////////////////
00007 // STL
00008 #include <iosfwd>
00009 #include <list>
00010 #include <map>
00011 // Boost
00012 #include <boost/static_assert.hpp>
00013 #include <boost/type_traits/is_same.hpp>
00014 // StdAir
00015 #include <stdair/bom/BomHolder.hpp>
00016 #include <stdair/bom/BomManager.hpp>
00017 #include <stdair/factory/FacAbstract.hpp>
00018 #include <stdair/factory/FacBom.hpp>
00019 // Stdair BOM Objects
00020 #include <stdair/bom/SegmentDate.hpp>
00021 
00022 
00023 namespace stdair {
00024 
00028   class FacBomManager : public FacAbstract {
00029   public:
00030     // ///////////// Business methods. ////////////
00039     template <typename OBJECT2, typename OBJECT1>
00040     static BomHolder<OBJECT2>* getBomHolderPtr (OBJECT1&);
00041 
00051     template <typename OBJECT2, typename OBJECT1> 
00052     static BomHolder<OBJECT2>& addBomHolder (OBJECT1&);
00053 
00065     template <typename OBJECT1, typename OBJECT2>
00066     static void addToList (OBJECT1&, OBJECT2&);
00067 
00080     template <typename OBJECT1, typename OBJECT2>
00081     static void addToMap (OBJECT1&, OBJECT2&, const MapKey_T&);
00082 
00094     template <typename OBJECT1, typename OBJECT2>
00095     static void addToMap (OBJECT1&, OBJECT2&);
00096 
00108     template <typename OBJECT1, typename OBJECT2>
00109     static void addToListAndMap (OBJECT1&, OBJECT2&);
00110 
00123     template <typename OBJECT1, typename OBJECT2>
00124     static void addToListAndMap (OBJECT1&, OBJECT2&, const MapKey_T&);
00125 
00132     template <typename PARENT, typename CHILD>
00133     static void linkWithParent (PARENT&, CHILD&);
00134 
00145     template <typename OBJECT2, typename OBJECT1>
00146     static void cloneHolder (OBJECT1&, const OBJECT1&);
00147 
00148 
00149   private:
00162     template <typename OBJECT1, typename OBJECT2>
00163     static void addToList (BomHolder<OBJECT2>&, OBJECT1&, OBJECT2&);
00164 
00178     template <typename OBJECT1, typename OBJECT2>
00179     static void addToMap (BomHolder<OBJECT2>&, OBJECT1&, OBJECT2&,
00180                           const MapKey_T&);
00181 
00190     template <typename OBJECT2, typename OBJECT1>
00191     static BomHolder<OBJECT2>& getBomHolder (OBJECT1&);
00192 
00193 
00194   protected:
00200     FacBomManager() { }
00201 
00202   public:
00206     ~FacBomManager() { }
00207   };
00208 
00209   // ////////////////////////////////////////////////////////////////////
00210   // Public business method.
00211   // Compile time assertation to check OBJECT1 and OBJECT2 types.
00212   template <typename OBJECT2, typename OBJECT1> 
00213   BomHolder<OBJECT2>& FacBomManager::addBomHolder (OBJECT1& ioObject1) {
00214 
00215     //
00216     // Compile time assertation: this function must never be called with the
00217     // following list of couple types:
00218     // <SegmentDate, SegmentDate>
00219     //
00220     BOOST_STATIC_ASSERT ((boost::is_same<OBJECT1, SegmentDate>::value == false
00221                           || boost::is_same<OBJECT2, SegmentDate>::value == false));    
00222 
00223     BomHolder<OBJECT2>* lBomHolder_ptr =
00224       &FacBom<BomHolder<OBJECT2> >::instance().create();
00225 
00226     const bool hasInsertBeenSuccessful =
00227       ioObject1._holderMap.insert (typename HolderMap_T::
00228                                    value_type (&typeid (OBJECT2),
00229                                                lBomHolder_ptr)).second;
00230     assert (hasInsertBeenSuccessful == true);
00231 
00232     return *lBomHolder_ptr;
00233   }
00234   
00235   // ////////////////////////////////////////////////////////////////////
00236   // Public business method.
00237   // Compile time assertation to check OBJECT1 and OBJECT2 types.
00238   template <typename OBJECT2, typename OBJECT1> 
00239   BomHolder<OBJECT2>* FacBomManager::getBomHolderPtr (OBJECT1& ioObject1) {
00240 
00241     //
00242     // Compile time assertation: this function must never be called with the
00243     // following list of couple types:
00244     // <SegmentDate, SegmentDate>
00245     // 
00246     BOOST_STATIC_ASSERT ((boost::is_same<OBJECT1, SegmentDate>::value == false
00247                           || boost::is_same<OBJECT2, SegmentDate>::value == false));            
00248 
00249     BomHolder<OBJECT2>* lBomHolder_ptr = NULL;
00250 
00251     // Find the corresponding BomHolder within the object1, if existing.
00252     HolderMap_T::const_iterator itHolder =
00253       ioObject1._holderMap.find (&typeid (OBJECT2));
00254 
00255     if (itHolder != ioObject1._holderMap.end()) {
00256       lBomHolder_ptr = static_cast<BomHolder<OBJECT2>*> (itHolder->second);
00257     }
00258 
00259     return lBomHolder_ptr;
00260   }
00261 
00262   // ////////////////////////////////////////////////////////////////////
00263   // Private method.
00264   template <typename OBJECT2, typename OBJECT1> 
00265   BomHolder<OBJECT2>& FacBomManager::getBomHolder (OBJECT1& ioObject1) {
00266 
00267     BomHolder<OBJECT2>* lBomHolder_ptr = NULL;
00268 
00269     // Find the corresponding BomHolder within the object1. If it does
00270     // not exist, then create one.
00271     HolderMap_T::const_iterator itHolder =
00272       ioObject1._holderMap.find (&typeid (OBJECT2));
00273 
00274     if (itHolder == ioObject1._holderMap.end()) {
00275       lBomHolder_ptr = &addBomHolder<OBJECT2, OBJECT1> (ioObject1);
00276 
00277     } else {
00278       lBomHolder_ptr = static_cast<BomHolder<OBJECT2>*> (itHolder->second);
00279     }
00280 
00281     assert (lBomHolder_ptr != NULL);
00282 
00283     return *lBomHolder_ptr;
00284   }
00285   
00286   // ////////////////////////////////////////////////////////////////////
00287   // Private method.
00288   template <typename OBJECT1, typename OBJECT2>
00289   void FacBomManager::addToList (BomHolder<OBJECT2>& ioBomHolder,
00290                                  OBJECT1& ioObject1, OBJECT2& ioObject2) {
00291     ioBomHolder._bomList.push_back (&ioObject2);
00292   }
00293   
00294   // ////////////////////////////////////////////////////////////////////
00295   // Public business method.
00296   // This method is specialized for the following couple types:
00297   // <SegmentDate, SegmentDate>
00298   template <typename OBJECT1, typename OBJECT2>
00299   void FacBomManager::addToList (OBJECT1& ioObject1, OBJECT2& ioObject2) {
00300 
00301     BomHolder<OBJECT2>& lBomHolder = getBomHolder<OBJECT2> (ioObject1);
00302 
00303     addToList<OBJECT1, OBJECT2> (lBomHolder, ioObject1, ioObject2);
00304   }
00305   
00306   // ////////////////////////////////////////////////////////////////////
00307   // Private method.
00308   template <typename OBJECT1, typename OBJECT2>
00309   void FacBomManager::addToMap (BomHolder<OBJECT2>& ioBomHolder,
00310                                 OBJECT1& ioObject1, OBJECT2& ioObject2,
00311                                 const MapKey_T& iKey) {
00312 
00313     const bool insertionSucceeded =
00314       ioBomHolder._bomMap.insert (typename std::map<const MapKey_T, OBJECT2*>::
00315                                   value_type (iKey, &ioObject2)).second;
00316 
00317     if (insertionSucceeded == false) {
00318       // Build a nice message, so that the error be fully explicit
00319       std::ostringstream oStr;
00320       oStr << "The given object ('" << iKey
00321            << "') can not be added to the map of '" << ioObject1.describeKey()
00322            << "' object. That map already contains: '";
00323 
00324       unsigned int idx = 0;
00325       for (typename std::map<const MapKey_T, OBJECT2*>::const_iterator iter =
00326              ioBomHolder._bomMap.begin(); 
00327            iter != ioBomHolder._bomMap.end(); ++iter, ++idx) {
00328         const OBJECT2* lCurrentObject_ptr = iter->second;
00329         assert (lCurrentObject_ptr != NULL);
00330 
00331         if (idx != 0) {
00332           oStr << "; ";
00333         }
00334         oStr << lCurrentObject_ptr->describeKey();
00335       }
00336       oStr << "'";
00337 
00338       STDAIR_LOG_ERROR (oStr.str());
00339       throw ObjectLinkingException (oStr.str());
00340     }    
00341   }
00342   
00343   // ////////////////////////////////////////////////////////////////////
00344   // Public business method.
00345   // Compile time assertation to check OBJECT1 and OBJECT2 types.
00346   template <typename OBJECT1, typename OBJECT2> void FacBomManager::
00347   addToMap (OBJECT1& ioObject1, OBJECT2& ioObject2, const MapKey_T& iKey) {
00348 
00349     //
00350     // Compile time assertation: this function must never be called with the
00351     // following list of couple types:
00352     // <SegmentDate, SegmentDate>
00353     // 
00354     BOOST_STATIC_ASSERT ((boost::is_same<OBJECT1, SegmentDate>::value == false
00355                           || boost::is_same<OBJECT2, SegmentDate>::value == false));          
00356 
00357     BomHolder<OBJECT2>& lBomHolder = getBomHolder<OBJECT2> (ioObject1);
00358 
00359     addToMap<OBJECT1, OBJECT2> (lBomHolder, ioObject1, ioObject2, iKey);
00360   }
00361   
00362   // Public business method.
00363   // Compile time assertation to check OBJECT1 and OBJECT2 types.
00364   // ////////////////////////////////////////////////////////////////////
00365   template <typename OBJECT1, typename OBJECT2>
00366   void FacBomManager::addToMap (OBJECT1& ioObject1, OBJECT2& ioObject2) {
00367 
00368     //
00369     // Compile time assertation: this function must never be called with the
00370     // following list of couple types:
00371     // <SegmentDate, SegmentDate>
00372     // 
00373     BOOST_STATIC_ASSERT ((boost::is_same<OBJECT1, SegmentDate>::value == false
00374                           || boost::is_same<OBJECT2, SegmentDate>::value == false));
00375     
00376     const MapKey_T& lKey = ioObject2.describeKey();
00377     addToMap (ioObject1, ioObject2, lKey);
00378   }
00379   
00380   // ////////////////////////////////////////////////////////////////////
00381   // Public business method.
00382   // Compile time assertation to check OBJECT1 and OBJECT2 types.
00383   template <typename OBJECT1, typename OBJECT2>
00384   void FacBomManager::addToListAndMap (OBJECT1& ioObject1, OBJECT2& ioObject2,
00385                                        const MapKey_T& iKey) {
00386     //
00387     // Compile time assertation: this function must never be called with the
00388     // following list of couple types:
00389     // <SegmentDate, SegmentDate>
00390     // 
00391     BOOST_STATIC_ASSERT ((boost::is_same<OBJECT1, SegmentDate>::value == false
00392                           || boost::is_same<OBJECT2, SegmentDate>::value == false));              
00393     
00394     BomHolder<OBJECT2>& lBomHolder = getBomHolder<OBJECT2> (ioObject1);
00395 
00396     addToList<OBJECT1, OBJECT2> (lBomHolder, ioObject1, ioObject2);
00397     addToMap<OBJECT1, OBJECT2> (lBomHolder, ioObject1, ioObject2, iKey);
00398   }
00399   
00400   // ////////////////////////////////////////////////////////////////////
00401   // Public business method.
00402   // Compile time assertation to check OBJECT1 and OBJECT2 types.
00403   template <typename OBJECT1, typename OBJECT2> void FacBomManager::
00404   addToListAndMap (OBJECT1& ioObject1, OBJECT2& ioObject2) {
00405 
00406     //
00407     // Compile time assertation: this function must never be called with the
00408     // following list of couple types:
00409     // <SegmentDate, SegmentDate>
00410     // 
00411     BOOST_STATIC_ASSERT ((boost::is_same<OBJECT1, SegmentDate>::value == false
00412                           || boost::is_same<OBJECT2, SegmentDate>::value == false));            
00413     
00414     const MapKey_T& lKey = ioObject2.describeKey();
00415     addToListAndMap<OBJECT1, OBJECT2> (ioObject1, ioObject2, lKey);
00416   }
00417 
00418   // Public business method valid for all PARENT and CHILD types.
00419   // (No compile time assertation to check PARENT and CHILD types.)
00420   // ////////////////////////////////////////////////////////////////////
00421   template <typename PARENT, typename CHILD> void FacBomManager::
00422   linkWithParent (PARENT& ioParent,  CHILD& ioChild) {
00423     ioChild._parent = &ioParent;
00424   }
00425   
00426   // ////////////////////////////////////////////////////////////////////
00427   // Public business method valid for all PARENT and CHILD types.
00428   // (No compile time assertation to check PARENT and CHILD types.)
00429   template <typename OBJECT2, typename OBJECT1> void FacBomManager::
00430   cloneHolder (OBJECT1& ioDest, const OBJECT1& iOri) {
00431 
00432     const BomHolder<OBJECT2>& lOriginHolder = 
00433       BomManager::getBomHolder<OBJECT2> (iOri);
00434 
00435     BomHolder<OBJECT2>& lDestHolder = getBomHolder<OBJECT2> (ioDest);
00436     lDestHolder._bomList = lOriginHolder._bomList;
00437     lDestHolder._bomMap = lOriginHolder._bomMap;
00438   }
00439 
00440   // ////////////////////////////////////////////////////////////////////
00441   //
00442   // Specialization of the template method addToList above for the types
00443   // <SegmentDate, SegmentDate>.
00444   // Add an element to the marketing segment date list of a segment date.
00445   //
00446   // ////////////////////////////////////////////////////////////////////
00447 
00448   template<>
00449   inline void FacBomManager::addToList <SegmentDate,SegmentDate>
00450   (SegmentDate& ioSegmentDate,
00451    SegmentDate& ioMarketingSegmentDate) {
00452     
00453     ioSegmentDate._marketingSegmentDateList.push_back(&ioMarketingSegmentDate);
00454   }
00455   
00456   // ////////////////////////////////////////////////////////////////////
00457   //
00458   // TODO:
00459   // This specialization is needed for all the objects in the current
00460   // BOM tree.
00461   // (An inventory is the parent of flight dates, a flight date is the
00462   // parent of segment dates and leg dates, ...)
00463   //
00464   // ////////////////////////////////////////////////////////////////////
00465 
00466 
00467 }
00468 
00469 // ////////////////////////////////////////////////////////////////////
00470 
00471 #endif // __STDAIR_FAC_FACBOMMANAGER_HPP