00001 #ifndef DataFormats_Common_DetSetLazyVector_h
00002 #define DataFormats_Common_DetSetLazyVector_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <algorithm>
00031 #include <vector>
00032
00033 #include "boost/concept_check.hpp"
00034 #include "boost/iterator/transform_iterator.hpp"
00035 #include "boost/shared_ptr.hpp"
00036
00037 #include "DataFormats/Common/interface/traits.h"
00038 #include "DataFormats/Common/interface/DetSet.h"
00039 #include "FWCore/Utilities/interface/EDMException.h"
00040 #include "DataFormats/Common/interface/Ref.h"
00041
00042 namespace edm {
00043
00044
00045
00046 template <class T> class DetSetLazyVector;
00047
00048
00049
00050
00051
00052 namespace dslvdetail
00053 {
00054
00055 inline
00056 void _throw_range(det_id_type i)
00057 {
00058 throw edm::Exception(errors::InvalidReference)
00059 << "DetSetLazyVector::operator[] called with index not in collection;\n"
00060 << "index value: " << i;
00061 }
00062 }
00063
00064 namespace dslv {
00065 template< typename T>
00066 class LazyGetter {
00067 public:
00068 virtual ~LazyGetter() {}
00069 virtual void fill(DetSet<T>&) = 0;
00070 };
00071 template<typename T>
00072 struct LazyAdapter : public std::unary_function<const DetSet<T>&, const DetSet<T>&> {
00073 LazyAdapter(boost::shared_ptr<LazyGetter<T> > iGetter): getter_(iGetter) {}
00074 const DetSet<T>& operator()(const DetSet<T>& iUpdate) const {
00075 if(iUpdate.data.empty() && getter_) {
00076
00077 DetSet<T>& temp = const_cast< DetSet<T>& >(iUpdate);
00078 getter_->fill(temp);
00079 std::sort(temp.begin(),temp.end());
00080 }
00081 return iUpdate;
00082 }
00083 private:
00084 boost::shared_ptr<LazyGetter<T> > getter_;
00085 };
00086 }
00087
00088
00089 namespace refhelper {
00090 template<typename T>
00091 struct FindDetSetForDetSetLazyVector : public std::binary_function<const DetSetLazyVector<T>&, edm::det_id_type, const DetSet<T>*> {
00092 typedef FindDetSetForDetSetLazyVector<T> self;
00093 typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) const {
00094 return &(*(iContainer.find(iIndex)));
00095 }
00096 };
00097 }
00098
00099 template <class T>
00100 class DetSetLazyVector
00101 {
00104 BOOST_CLASS_REQUIRE(T, boost, LessThanComparableConcept);
00105 public:
00106
00107 typedef DetSet<T> detset;
00108 typedef detset value_type;
00109 typedef std::vector<value_type> collection_type;
00110
00111 typedef detset const& const_reference;
00112
00113
00114 typedef boost::transform_iterator< dslv::LazyAdapter<T>, typename collection_type::const_iterator > const_iterator;
00115 typedef typename collection_type::size_type size_type;
00116
00119
00120
00121
00122
00123
00124 DetSetLazyVector() {}
00125
00126 DetSetLazyVector(boost::shared_ptr<dslv::LazyGetter<T> > iGetter, const std::vector<det_id_type>& iDets) :
00127 sets_(),
00128 getter_(iGetter) {
00129 sets_.reserve(iDets.size());
00130 det_id_type sanityCheck = 0;
00131 for(std::vector<det_id_type>::const_iterator itDetId = iDets.begin(), itDetIdEnd = iDets.end();
00132 itDetId != itDetIdEnd;
00133 ++itDetId) {
00134 assert(sanityCheck <= *itDetId && "vector of det_id_type was not ordered");
00135 sanityCheck = *itDetId;
00136 sets_.push_back(DetSet<T>(*itDetId));
00137 }
00138 }
00139
00140 void swap(DetSetLazyVector& other);
00141
00142
00143
00145 bool empty() const;
00146
00148 size_type size() const;
00149
00150
00151
00152
00153
00156 const_iterator find(det_id_type id) const;
00157
00161 const_reference operator[](det_id_type i) const;
00162
00164 const_iterator begin() const;
00165
00167 const_iterator end() const;
00168
00171
00172
00173 private:
00174 collection_type sets_;
00175 boost::shared_ptr<dslv::LazyGetter<T> > getter_;
00176 };
00177
00178 template <class T>
00179 inline
00180 void
00181 DetSetLazyVector<T>::swap(DetSetLazyVector<T>& other)
00182 {
00183 sets_.swap(other.sets_);
00184 std::swap(getter_,other.getter_);
00185 }
00186
00187 template <class T>
00188 inline
00189 bool
00190 DetSetLazyVector<T>::empty() const
00191 {
00192 return sets_.empty();
00193 }
00194
00195 template <class T>
00196 inline
00197 typename DetSetLazyVector<T>::size_type
00198 DetSetLazyVector<T>::size() const
00199 {
00200 return sets_.size();
00201 }
00202
00203 template <class T>
00204 inline
00205 typename DetSetLazyVector<T>::const_iterator
00206 DetSetLazyVector<T>::find(det_id_type id) const
00207 {
00208 if(empty()) {
00209 dslv::LazyAdapter<T> adapter(getter_);
00210 return boost::make_transform_iterator(sets_.end(),adapter);
00211 }
00212
00213
00214 std::pair<typename collection_type::const_iterator,typename collection_type::const_iterator> p =
00215 std::equal_range(sets_.begin(), sets_.end(), id);
00216 if (p.first == p.second) {
00217 dslv::LazyAdapter<T> adapter(getter_);
00218 return boost::make_transform_iterator(sets_.end(),adapter);
00219 }
00220
00221
00222 assert(std::distance(p.first, p.second) == 1);
00223 dslv::LazyAdapter<T> adapter(getter_);
00224 return boost::make_transform_iterator(p.first,adapter);
00225 }
00226
00227 template <class T>
00228 inline
00229 typename DetSetLazyVector<T>::const_reference
00230 DetSetLazyVector<T>::operator[](det_id_type i) const
00231 {
00232
00233
00234 const_iterator it = this->find(i);
00235 if (it == this->end()) dslvdetail::_throw_range(i);
00236 return *it;
00237 }
00238
00239 template <class T>
00240 inline
00241 typename DetSetLazyVector<T>::const_iterator
00242 DetSetLazyVector<T>::begin() const
00243 {
00244 dslv::LazyAdapter<T> adapter(getter_);
00245 return boost::make_transform_iterator(sets_.begin(),adapter);
00246 }
00247
00248 template <class T>
00249 inline
00250 typename DetSetLazyVector<T>::const_iterator
00251 DetSetLazyVector<T>::end() const
00252 {
00253 dslv::LazyAdapter<T> adapter(getter_);
00254 return boost::make_transform_iterator(sets_.end(),adapter);
00255 }
00256
00257
00258 template <class T>
00259 inline
00260 void
00261 swap(DetSetLazyVector<T>& a, DetSetLazyVector<T>& b)
00262 {
00263 a.swap(b);
00264 }
00265
00266
00267
00268 namespace refhelper {
00269 template<typename T>
00270 struct FindForDetSetLazyVector : public std::binary_function<const DetSetLazyVector<T>&, std::pair<det_id_type, typename DetSet<T>::collection_type::size_type>, const T*> {
00271 typedef FindForDetSetLazyVector<T> self;
00272 typename self::result_type operator()(typename self::first_argument_type iContainer, typename self::second_argument_type iIndex) {
00273 return &(*(iContainer.find(iIndex.first)->data.begin()+iIndex.second));
00274 }
00275 };
00276
00277 template<typename T>
00278 struct FindTrait<DetSetLazyVector<T>,T> {
00279 typedef FindForDetSetLazyVector<T> value;
00280 };
00281 }
00282
00283
00284
00285 template<class HandleT>
00286 Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
00287 makeRefToDetSetLazyVector(const HandleT& iHandle,
00288 det_id_type iDetID,
00289 typename HandleT::element_type::value_type::const_iterator itIter) {
00290 typedef typename HandleT::element_type Vec;
00291 typename Vec::value_type::collection_type::size_type index=0;
00292 typename Vec::const_iterator itFound = iHandle->find(iDetID);
00293 index += (itIter- itFound->data.begin());
00294 return Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type> (iHandle,std::make_pair(iDetID,index));
00295 }
00296
00297 template<class HandleT>
00298 Ref< typename HandleT::element_type, typename HandleT::element_type::value_type::value_type>
00299 makeRefToDetSetLazyVector(const HandleT& iHandle,
00300 det_id_type iDetID,
00301 typename HandleT::element_type::value_type::iterator itIter) {
00302 typedef typename HandleT::element_type Vec;
00303 typename Vec::detset::const_iterator itIter2 = itIter;
00304 return makeRefToDetSetLazyVector(iHandle,iDetID,itIter2);
00305 }
00306 }
00307 #endif