CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch12/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/traits.h"
00035 #include "DataFormats/Common/interface/DetSet.h"
00036 #include "FWCore/Utilities/interface/EDMException.h"
00037 
00038 #include "DataFormats/Common/interface/Ref.h"
00039 #include "DataFormats/Common/interface/DetSetVector.h"
00040 #include "DataFormats/Common/interface/Handle.h"
00041 #include "DataFormats/Common/interface/OrphanHandle.h"
00042 #include "DataFormats/Common/interface/TestHandle.h"
00043 
00044 namespace edm {
00045 
00046   //------------------------------------------------------------
00047   // Forward declarations
00048   template <typename T, typename C> class DetSetRefVector;
00049 
00050   //------------------------------------------------------------
00051   // Helper function, to regularize throwing of exceptions.
00052   //------------------------------------------------------------
00053 
00054   namespace dsrvdetail
00055   {
00056     // Throw an edm::Exception with an appropriate message
00057     inline
00058     void _throw_range(det_id_type i)
00059     {
00060       Exception::throwThis(errors::InvalidReference,
00061         "DetSetRefVector::operator[] called with index not in collection;\nindex value: ", i);
00062     }
00063   }
00064 
00065   //------------------------------------------------------------
00066   //
00067   namespace refhelper {
00068     template<typename T, typename C >
00069     struct FindDetSetForDetSetVector : public std::binary_function<const C &, edm::det_id_type, const DetSet<T>*> {
00070       typedef FindDetSetForDetSetVector<T,C> self;
00071       typename self::result_type operator()(typename self::first_argument_type iContainer,  typename self::second_argument_type iIndex) const {
00072         return &(*(iContainer.find(iIndex)));
00073       }
00074     };
00075   }
00076   
00077   //allow comparison of edm::Ref<...> to the det_it_type.  This allows searching without dereferencing the edm::Ref
00078   template <typename T, typename C=DetSetVector<T> >
00079     struct CompareRefDetSet {
00080     typedef Ref<C, DetSet<T>, refhelper::FindDetSetForDetSetVector<T,C> > ref_type; 
00081       bool operator()(const ref_type& iRef, det_id_type iId) {
00082         return iRef.key() < iId;
00083       }
00084       bool operator()(det_id_type iId, const ref_type& iRef) {
00085         return iId < iRef.key();
00086       }
00087     };
00088 
00089   template <typename T, typename C=DetSetVector<T> >
00090   class DetSetRefVector 
00091   {
00094     BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
00095   public:
00096 
00097     typedef DetSet<T>           detset;
00098     typedef detset              value_type;
00099     typedef Ref<C, DetSet<T>, refhelper::FindDetSetForDetSetVector<T,C> > ref_type;
00100     typedef std::vector<ref_type> collection_type;
00101 
00102     typedef detset const&  const_reference;
00103 
00104     //iterator returns a DetSet<T> instead of a Ref<...>
00105     typedef boost::indirect_iterator<typename collection_type::const_iterator> const_iterator;
00106     typedef typename collection_type::size_type      size_type;
00107 
00110 
00111     // Add the following only if needed.
00112     //template <class InputIterator>
00113     //DetSetRefVector(InputIterator b, InputIterator e);
00114 
00115     DetSetRefVector() {}
00116     
00117       DetSetRefVector(const Handle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
00118         sets_.reserve(iDets.size());
00119         det_id_type sanityCheck = 0;
00120         for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
00121             itDetIdEnd = iDets.end();
00122             itDetId != itDetIdEnd;
00123             ++itDetId) {
00124           assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00125           sanityCheck = *itDetId;
00126           //the last 'false' says to not get the data right now
00127           sets_.push_back(ref_type(iHandle, *itDetId, false));
00128         }
00129       }
00130 
00131       DetSetRefVector(const OrphanHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
00132         sets_.reserve(iDets.size());
00133         det_id_type sanityCheck = 0;
00134         for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
00135             itDetIdEnd = iDets.end();
00136             itDetId != itDetIdEnd;
00137             ++itDetId) {
00138           assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00139           sanityCheck = *itDetId;
00140           //the last 'false' says to not get the data right now
00141           sets_.push_back(ref_type(iHandle, *itDetId, false));
00142         }
00143       }
00144 
00145       DetSetRefVector(const TestHandle<C>& iHandle, const std::vector<det_id_type>& iDets) : sets_() {
00146         sets_.reserve(iDets.size());
00147         det_id_type sanityCheck = 0;
00148         for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(),
00149             itDetIdEnd = iDets.end();
00150             itDetId != itDetIdEnd;
00151             ++itDetId) {
00152           assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00153           sanityCheck = *itDetId;
00154           //the last 'false' says to not get the data right now
00155           sets_.push_back(ref_type(iHandle, *itDetId, false));
00156         }
00157       }
00158 
00159     void swap(DetSetRefVector& other);
00160 
00161     DetSetRefVector& operator=(DetSetRefVector const& rhs);
00162 
00164     bool empty() const;
00165 
00167     size_type size() const;
00168 
00169     // Do we need a short-hand method to return the number of T
00170     // instances? If so, do we optimize for size (calculate on the
00171     // fly) or speed (keep a current cache)?
00172 
00175     const_iterator find(det_id_type id) const;
00176 
00180     const_reference operator[](det_id_type i) const;
00181 
00183     const_iterator begin() const;
00184 
00186     const_iterator end() const;
00187 
00190     //void post_insert();
00191 
00192   private:
00193     collection_type   sets_;
00194 
00195   };
00196 
00197   template <typename T, typename C>
00198   inline
00199   void
00200   DetSetRefVector<T,C>::swap(DetSetRefVector<T,C>& other) {
00201     sets_.swap(other.sets_);
00202   }
00203 
00204   template <typename T, typename C>
00205   inline
00206   DetSetRefVector<T ,C>&
00207   DetSetRefVector<T, C>::operator=(DetSetRefVector<T,C> const& rhs) {
00208     DetSetRefVector<T, C> temp(rhs);
00209     this->swap(temp);
00210     return *this;
00211   }
00212 
00213   template <typename T, typename C>
00214   inline
00215   bool
00216   DetSetRefVector<T,C>::empty() const 
00217   {
00218     return sets_.empty();
00219   }
00220 
00221   template <typename T, typename C>
00222   inline
00223   typename DetSetRefVector<T,C>::size_type
00224   DetSetRefVector<T,C>::size() const
00225   {
00226     return sets_.size();
00227   }
00228 
00229   template <typename T, typename C>
00230   inline
00231   typename DetSetRefVector<T,C>::const_iterator
00232   DetSetRefVector<T,C>::find(det_id_type id) const
00233   {
00234     if(empty()) {
00235       return sets_.end();
00236     }
00237     std::pair<typename collection_type::const_iterator,typename collection_type::const_iterator> p = 
00238     std::equal_range(sets_.begin(), sets_.end(), id, CompareRefDetSet<T,C>());
00239     if (p.first == p.second) return sets_.end();
00240     // The range indicated by [p.first, p.second) should be exactly of
00241     // length 1.
00242     assert(std::distance(p.first, p.second) == 1);
00243     return p.first;
00244   }
00245 
00246   template <typename T, typename C>
00247   inline
00248   typename DetSetRefVector<T,C>::const_reference
00249   DetSetRefVector<T,C>::operator[](det_id_type i) const 
00250   {
00251     // Find the right DetSet, and return a reference to it.  Throw if
00252     // there is none.
00253     const_iterator it = this->find(i);
00254     if (it == this->end()) dsrvdetail::_throw_range(i);
00255     return *it;
00256   }
00257 
00258   template <typename T, typename C>
00259   inline
00260   typename DetSetRefVector<T,C>::const_iterator
00261   DetSetRefVector<T,C>::begin() const
00262   {
00263     return sets_.begin();
00264   }
00265 
00266   template <typename T, typename C>
00267   inline
00268   typename DetSetRefVector<T,C>::const_iterator
00269   DetSetRefVector<T,C>::end() const
00270   {
00271     return sets_.end();
00272   }
00273 
00274   // Free swap function
00275   template <typename T, typename C>
00276   inline
00277   void
00278   swap(DetSetRefVector<T, C>& a, DetSetRefVector<T, C>& b) {
00279     a.swap(b);
00280   }
00281 
00282 //specialize behavior of edm::Ref to get access to the 'Det'
00283 
00284   namespace refhelper {
00285     template<typename T, typename C>
00286     struct FindForDetSetRefVector : public std::binary_function<const DetSetRefVector<T,C>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
00287       typedef FindForDetSetRefVector<T,C> self;
00288       typename self::result_type operator()(typename self::first_argument_type iContainer,  typename self::second_argument_type iIndex) {
00289         return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
00290       }
00291     };
00292     
00293     template<typename T, typename C> 
00294       struct FindTrait<DetSetRefVector<T,C>,T> {
00295         typedef FindForDetSetRefVector<T,C> value;
00296       };
00297   }
00298   
00299    //helper function to make it easier to create a edm::Ref
00300    
00301    template<class HandleT>
00302    Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> 
00303    makeRefToDetSetRefVector(const HandleT& iHandle, 
00304              det_id_type iDetID,
00305              typename HandleT::element_type::value_type::const_iterator itIter) {
00306       typedef typename HandleT::element_type Vec;
00307       typename Vec::value_type::collection_type::size_type index=0;
00308       typename Vec::const_iterator itFound = iHandle->find(iDetID);
00309       index += (itIter- itFound->data.begin());
00310       return    Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> (iHandle,std::make_pair(iDetID,index));
00311    }
00312    
00313    template<class HandleT>
00314    Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> 
00315    makeRefToDetSetRefVector(const HandleT& iHandle, 
00316              det_id_type iDetID,
00317              typename HandleT::element_type::value_type::iterator itIter) {
00318       typedef typename HandleT::element_type Vec;
00319       typename Vec::detset::const_iterator itIter2 = itIter;
00320       return makeRefToDetSetRefVector(iHandle,iDetID,itIter2);
00321    }
00322 }  
00323 #endif