CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/DataFormats/Common/interface/DetSetRefVector.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_DetSetRefVector_h
00002 #define DataFormats_Common_DetSetRefVector_h
00003 
00004 /*----------------------------------------------------------------------
00005   
00006 DetSeReftVector: A collection of homogeneous objects that can be used for
00007 an EDProduct. DetSetVector is *not* designed for use as a base class
00008 (it has no virtual functions).
00009 
00010 DetSetVector<T> contains a vector<DetSet<T> >, sorted on DetId, and
00011 provides fast (O(log n)) lookups, but only O(n) insertion.
00012 
00013 It provides an interface such that EdmRef2 can directly reference, and
00014 provide access to, individual T objects.
00015 
00016 The collection appears to the user as if it were a sequence of
00017 DetSet<T>; e.g., operator[] returns a DetSet<T>&. However, the
00018 argument to operator[] specifies the (DetId) identifier of the vector
00019 to be returned, *not* the ordinal number of the T to be returned.
00020 
00021                           ------------------
00022    It is critical that users DO NOT MODIFY the id data member of a
00023    DetSet object in a DetSetVector.
00024                           ------------------
00025 
00026 ----------------------------------------------------------------------*/
00027 
00028 #include <algorithm>
00029 #include <vector>
00030 
00031 #include "boost/concept_check.hpp"
00032 #include "boost/iterator/indirect_iterator.hpp"
00033 
00034 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00035 #include "DataFormats/Common/interface/traits.h"
00036 #include "DataFormats/Common/interface/DetSet.h"
00037 #include "FWCore/Utilities/interface/EDMException.h"
00038 
00039 #include "DataFormats/Common/interface/Ref.h"
00040 #include "DataFormats/Common/interface/DetSetVector.h"
00041 #include "DataFormats/Common/interface/Handle.h"
00042 #include "DataFormats/Common/interface/OrphanHandle.h"
00043 #include "DataFormats/Common/interface/TestHandle.h"
00044 
00045 namespace edm {
00046 
00047   //------------------------------------------------------------
00048   // Forward declarations
00049   template <typename T, typename C> class DetSetRefVector;
00050 
00051   //------------------------------------------------------------
00052   // Helper function, to regularize throwing of exceptions.
00053   //------------------------------------------------------------
00054 
00055   namespace dsrvdetail
00056   {
00057     // Throw an edm::Exception with an appropriate message
00058     inline
00059     void _throw_range(det_id_type i)
00060     {
00061       Exception::throwThis(errors::InvalidReference,
00062         "DetSetRefVector::operator[] called with index not in collection;\nindex value: ", i);
00063     }
00064   }
00065 
00066   //------------------------------------------------------------
00067   //
00068   namespace refhelper {
00069     template<typename T, typename C >
00070     struct FindDetSetForDetSetVector : public std::binary_function<const C &, edm::det_id_type, const DetSet<T>*> {
00071       typedef FindDetSetForDetSetVector<T,C> self;
00072       typename self::result_type operator()(typename self::first_argument_type iContainer,  typename self::second_argument_type iIndex) const {
00073         return &(*(iContainer.find(iIndex)));
00074       }
00075     };
00076   }
00077   
00078   //allow comparison of edm::Ref<...> to the det_it_type.  This allows searching without dereferencing the edm::Ref
00079   template <typename T, typename C=DetSetVector<T> >
00080     struct CompareRefDetSet {
00081     typedef Ref<C, DetSet<T>, refhelper::FindDetSetForDetSetVector<T,C> > ref_type; 
00082       bool operator()(const ref_type& iRef, det_id_type iId) {
00083         return iRef.key() < iId;
00084       }
00085       bool operator()(det_id_type iId, const ref_type& iRef) {
00086         return iId < iRef.key();
00087       }
00088     };
00089 
00090   template <typename T, typename C=DetSetVector<T> >
00091   class DetSetRefVector 
00092   {
00095     BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
00096   public:
00097 
00098     typedef DetSet<T>           detset;
00099     typedef detset              value_type;
00100     typedef Ref<C, DetSet<T>, refhelper::FindDetSetForDetSetVector<T,C> > ref_type;
00101     typedef std::vector<ref_type> collection_type;
00102 
00103     typedef detset const&  const_reference;
00104 
00105     //iterator returns a DetSet<T> instead of a Ref<...>
00106     typedef boost::indirect_iterator<typename collection_type::const_iterator> const_iterator;
00107     typedef typename collection_type::size_type      size_type;
00108 
00111 
00112     // Add the following only if needed.
00113     //template <class InputIterator>
00114     //DetSetRefVector(InputIterator b, InputIterator e);
00115 
00116     DetSetRefVector() {}
00117     
00118       DetSetRefVector(const Handle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
00119         sets_.reserve(iDets.size());
00120         det_id_type sanityCheck = 0;
00121         for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
00122             itDetIdEnd = iDets.end();
00123             itDetId != itDetIdEnd;
00124             ++itDetId) {
00125           assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00126           sanityCheck = *itDetId;
00127           //the last 'false' says to not get the data right now
00128           sets_.push_back(ref_type(iHandle, *itDetId, false));
00129         }
00130       }
00131 
00132       DetSetRefVector(const OrphanHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
00133         sets_.reserve(iDets.size());
00134         det_id_type sanityCheck = 0;
00135         for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
00136             itDetIdEnd = iDets.end();
00137             itDetId != itDetIdEnd;
00138             ++itDetId) {
00139           assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00140           sanityCheck = *itDetId;
00141           //the last 'false' says to not get the data right now
00142           sets_.push_back(ref_type(iHandle, *itDetId, false));
00143         }
00144       }
00145 
00146       DetSetRefVector(const TestHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
00147         sets_.reserve(iDets.size());
00148         det_id_type sanityCheck = 0;
00149         for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
00150             itDetIdEnd = iDets.end();
00151             itDetId != itDetIdEnd;
00152             ++itDetId) {
00153           assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00154           sanityCheck = *itDetId;
00155           //the last 'false' says to not get the data right now
00156           sets_.push_back(ref_type(iHandle, *itDetId, false));
00157         }
00158       }
00159 
00160     void swap(DetSetRefVector& other);
00161 
00162     DetSetRefVector& operator=(DetSetRefVector const& rhs);
00163 
00165     bool empty() const;
00166 
00168     size_type size() const;
00169 
00170     // Do we need a short-hand method to return the number of T
00171     // instances? If so, do we optimize for size (calculate on the
00172     // fly) or speed (keep a current cache)?
00173 
00176     const_iterator find(det_id_type id) const;
00177 
00181     const_reference operator[](det_id_type i) const;
00182 
00184     const_iterator begin() const;
00185 
00187     const_iterator end() const;
00188 
00191     //void post_insert();
00192 
00193     //Needed for ROOT storage
00194     CMS_CLASS_VERSION(10)
00195 
00196   private:
00197     collection_type   sets_;
00198 
00199   };
00200 
00201   template <typename T, typename C>
00202   inline
00203   void
00204   DetSetRefVector<T,C>::swap(DetSetRefVector<T,C>& other) {
00205     sets_.swap(other.sets_);
00206   }
00207 
00208   template <typename T, typename C>
00209   inline
00210   DetSetRefVector<T ,C>&
00211   DetSetRefVector<T, C>::operator=(DetSetRefVector<T,C> const& rhs) {
00212     DetSetRefVector<T, C> temp(rhs);
00213     this->swap(temp);
00214     return *this;
00215   }
00216 
00217   template <typename T, typename C>
00218   inline
00219   bool
00220   DetSetRefVector<T,C>::empty() const 
00221   {
00222     return sets_.empty();
00223   }
00224 
00225   template <typename T, typename C>
00226   inline
00227   typename DetSetRefVector<T,C>::size_type
00228   DetSetRefVector<T,C>::size() const
00229   {
00230     return sets_.size();
00231   }
00232 
00233   template <typename T, typename C>
00234   inline
00235   typename DetSetRefVector<T,C>::const_iterator
00236   DetSetRefVector<T,C>::find(det_id_type id) const
00237   {
00238     if(empty()) {
00239       return sets_.end();
00240     }
00241     std::pair<typename collection_type::const_iterator,typename collection_type::const_iterator> p = 
00242     std::equal_range(sets_.begin(), sets_.end(), id, CompareRefDetSet<T,C>());
00243     if (p.first == p.second) return sets_.end();
00244     // The range indicated by [p.first, p.second) should be exactly of
00245     // length 1.
00246     assert(std::distance(p.first, p.second) == 1);
00247     return p.first;
00248   }
00249 
00250   template <typename T, typename C>
00251   inline
00252   typename DetSetRefVector<T,C>::const_reference
00253   DetSetRefVector<T,C>::operator[](det_id_type i) const 
00254   {
00255     // Find the right DetSet, and return a reference to it.  Throw if
00256     // there is none.
00257     const_iterator it = this->find(i);
00258     if (it == this->end()) dsrvdetail::_throw_range(i);
00259     return *it;
00260   }
00261 
00262   template <typename T, typename C>
00263   inline
00264   typename DetSetRefVector<T,C>::const_iterator
00265   DetSetRefVector<T,C>::begin() const
00266   {
00267     return sets_.begin();
00268   }
00269 
00270   template <typename T, typename C>
00271   inline
00272   typename DetSetRefVector<T,C>::const_iterator
00273   DetSetRefVector<T,C>::end() const
00274   {
00275     return sets_.end();
00276   }
00277 
00278   // Free swap function
00279   template <typename T, typename C>
00280   inline
00281   void
00282   swap(DetSetRefVector<T, C>& a, DetSetRefVector<T, C>& b) {
00283     a.swap(b);
00284   }
00285 
00286 //specialize behavior of edm::Ref to get access to the 'Det'
00287 
00288   namespace refhelper {
00289     template<typename T, typename C>
00290     struct FindForDetSetRefVector : public std::binary_function<const DetSetRefVector<T,C>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
00291       typedef FindForDetSetRefVector<T,C> self;
00292       typename self::result_type operator()(typename self::first_argument_type iContainer,  typename self::second_argument_type iIndex) {
00293         return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
00294       }
00295     };
00296     
00297     template<typename T, typename C> 
00298       struct FindTrait<DetSetRefVector<T,C>,T> {
00299         typedef FindForDetSetRefVector<T,C> value;
00300       };
00301   }
00302   
00303    //helper function to make it easier to create a edm::Ref
00304    
00305    template<class HandleT>
00306    Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> 
00307    makeRefToDetSetRefVector(const HandleT& iHandle, 
00308              det_id_type iDetID,
00309              typename HandleT::element_type::value_type::const_iterator itIter) {
00310       typedef typename HandleT::element_type Vec;
00311       typename Vec::value_type::collection_type::size_type index=0;
00312       typename Vec::const_iterator itFound = iHandle->find(iDetID);
00313       index += (itIter- itFound->data.begin());
00314       return    Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> (iHandle,std::make_pair(iDetID,index));
00315    }
00316    
00317    template<class HandleT>
00318    Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> 
00319    makeRefToDetSetRefVector(const HandleT& iHandle, 
00320              det_id_type iDetID,
00321              typename HandleT::element_type::value_type::iterator itIter) {
00322       typedef typename HandleT::element_type Vec;
00323       typename Vec::detset::const_iterator itIter2 = itIter;
00324       return makeRefToDetSetRefVector(iHandle,iDetID,itIter2);
00325    }
00326 }  
00327 #endif