00001 #ifndef DataFormats_Common_MultiAssociation_h
00002 #define DataFormats_Common_MultiAssociation_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
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include <vector>
00053 #include <map>
00054 #include <boost/shared_ptr.hpp>
00055 #include <boost/utility.hpp>
00056 #include <boost/range.hpp>
00057 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00058 #include "DataFormats/Provenance/interface/ProductID.h"
00059
00060 namespace edm {
00061 namespace helper {
00066
00073 class IndexRangeAssociation {
00074 public:
00075 typedef std::pair<unsigned int, unsigned int> range;
00076
00077 IndexRangeAssociation() : isFilling_(false) {}
00078
00081 template<typename RefKey>
00082 range operator[](const RefKey &r) const {
00083 return get(r.id(), r.key());
00084 }
00085
00088 range get(const edm::ProductID & id, unsigned int t) const ;
00089
00091 bool contains(ProductID id) const ;
00092
00094 unsigned int size() const { return ref_offsets_.empty() ? 0 : ref_offsets_.size() - 1; }
00095
00097 bool empty() const { return ref_offsets_.empty(); }
00098
00103 class FastFiller : boost::noncopyable {
00104 public:
00106 FastFiller(IndexRangeAssociation &assoc, ProductID id, unsigned int size) ;
00107
00109 ~FastFiller() ;
00110
00112 template<typename RefKey>
00113 void insert(const RefKey &r, unsigned int startingOffset, unsigned int size) {
00114 insert(r.id(), r.key(), startingOffset, size);
00115 }
00116
00118 void insert(edm::ProductID id, unsigned int key, unsigned int startingOffset, unsigned int size) ;
00119 private:
00120 IndexRangeAssociation & assoc_;
00121 const ProductID id_;
00122 unsigned int start_, end_;
00124 int lastKey_;
00125 };
00126 friend class FastFiller;
00127
00128 void swap(IndexRangeAssociation &other) ;
00129
00130 static void throwUnexpectedProductID(ProductID found, ProductID expected, const char *where) ;
00131 private:
00132 typedef std::pair<edm::ProductID,unsigned int> id_off_pair;
00133 typedef std::vector<id_off_pair> id_offset_vector;
00134 typedef std::vector<int> offset_vector;
00135 id_offset_vector id_offsets_;
00136 offset_vector ref_offsets_;
00137
00138 bool isFilling_;
00139 struct IDComparator {
00140 bool operator()(const id_off_pair &p, const edm::ProductID &id) const { return p.first < id; }
00141 };
00142
00143
00144 };
00145
00146
00147 inline void swap(IndexRangeAssociation& lhs, IndexRangeAssociation& rhs) { lhs.swap(rhs); }
00148
00149 }
00150
00151 template<typename C>
00152 class MultiAssociation {
00153 public:
00154 typedef C Collection;
00155 typedef boost::sub_range<const Collection> const_range;
00156 typedef boost::sub_range<Collection> range;
00157
00158 MultiAssociation() {}
00159
00161 template<typename RefKey>
00162 const_range operator[](const RefKey &r) const {
00163 return get(r.id(), r.key());
00164 }
00165
00167 template<typename RefKey>
00168 range operator[](const RefKey &r) {
00169 return get(r.id(), r.key());
00170 }
00171
00173 template<typename RefKey>
00174 Collection getValues(const RefKey &r) const {
00175 return getValues(r.id(), r.key());
00176 }
00177
00179 bool contains(const edm::ProductID &id) const { return indices_.contains(id); }
00180
00182 const_range get(const edm::ProductID &id, unsigned int t) const ;
00183
00185 range get(const edm::ProductID &id, unsigned int t) ;
00186
00188 Collection getValues(const edm::ProductID &id, unsigned int t) const ;
00189
00190 void swap(MultiAssociation &other) {
00191 indices_.swap(other.indices_);
00192 data_.swap(other.data_);
00193 }
00194
00196 unsigned int dataSize() const { return data_.size(); }
00197
00199 unsigned int size() const { return indices_.size(); }
00200
00202 bool empty() const { return indices_.empty(); }
00203
00208 class FastFiller {
00209 public:
00210 template<typename HandleType>
00211 FastFiller(MultiAssociation &assoc, const HandleType &handle) :
00212 assoc_(assoc), indexFiller_(new IndexFiller(assoc_.indices_, handle.id(), handle->size())) {}
00213
00214 FastFiller(MultiAssociation &assoc, edm::ProductID id, unsigned int size) :
00215 assoc_(assoc), indexFiller_(new IndexFiller(assoc_.indices_, id, size)) {}
00216
00217 ~FastFiller() {}
00218
00220 template<typename KeyRef>
00221 void setValues(const KeyRef &k, const Collection &refs) { setValues(k.id(), k.key(), refs); }
00222
00224 void setValues(const edm::ProductID &id, unsigned int key, const Collection &refs);
00225 private:
00226 MultiAssociation & assoc_;
00227 typedef edm::helper::IndexRangeAssociation::FastFiller IndexFiller;
00228 boost::shared_ptr<IndexFiller> indexFiller_;
00229
00230 };
00231 friend class FastFiller;
00232
00233 template<typename HandleType>
00234 FastFiller fastFiller(const HandleType &handle) { return FastFiller(*this, handle); }
00235
00241 class LazyFiller {
00242 public:
00243 template<typename HandleType>
00244 LazyFiller(MultiAssociation &assoc, const HandleType &handle, bool fillOnExit=false) :
00245 assoc_(assoc),
00246 id_(handle.id()), size_(handle->size()),
00247 tempValues_(new TempValues()), fillOnExit_(fillOnExit) {}
00248 ~LazyFiller() { if (fillOnExit_) fill(); }
00249
00254 void fill();
00255
00257 void setFillOnExit(bool fillOnExit) { fillOnExit_ = fillOnExit; }
00258
00260 template<typename KeyRef>
00261 void setValues(const KeyRef &k, const Collection &refs) ;
00262
00265 template<typename KeyRef>
00266 void swapValues(const KeyRef &k, Collection &refs) ;
00267 private:
00268 typedef std::map<unsigned int, Collection> TempValues;
00269 MultiAssociation & assoc_;
00270 ProductID id_;
00271 unsigned int size_;
00272 boost::shared_ptr<TempValues> tempValues_;
00273 bool fillOnExit_;
00274 };
00275 friend class LazyFiller;
00276
00277 template<typename HandleType>
00278 LazyFiller lazyFiller(const HandleType &h, bool fillOnExit=false) { return LazyFiller(*this, h, fillOnExit); }
00279
00280
00281 CMS_CLASS_VERSION(10)
00282
00283 private:
00284 typedef helper::IndexRangeAssociation Indices;
00285 Indices indices_;
00286 Collection data_;
00287
00288 };
00289
00290
00291 template <typename C>
00292 inline void swap(MultiAssociation<C>& lhs, MultiAssociation<C>& rhs) { lhs.swap(rhs); }
00293
00294
00295 template<typename C>
00296 typename MultiAssociation<C>::const_range
00297 MultiAssociation<C>::get(const edm::ProductID & id, unsigned int key) const {
00298 Indices::range idxrange = indices_.get(id,key);
00299 return const_range(data_.begin()+idxrange.first, data_.begin()+idxrange.second);
00300 }
00301
00302 template<typename C>
00303 typename MultiAssociation<C>::range
00304 MultiAssociation<C>::get(const edm::ProductID & id, unsigned int key) {
00305 Indices::range idxrange = indices_.get(id,key);
00306 return range(data_.begin()+idxrange.first, data_.begin()+idxrange.second);
00307 }
00308
00309
00310 template<typename C>
00311 typename MultiAssociation<C>::Collection
00312 MultiAssociation<C>::getValues(const edm::ProductID & id, unsigned int key) const {
00313 Collection ret;
00314 const_range values = get(id,key);
00315 for (typename const_range::const_iterator it = values.begin(), ed = values.end(); it != ed; ++it) {
00316 ret.push_back(*it);
00317 }
00318 return ret;
00319 }
00320
00321 template<typename C>
00322 void MultiAssociation<C>::FastFiller::setValues(const edm::ProductID & id, unsigned int key, const Collection &vals) {
00323 indexFiller_->insert(id, key, assoc_.data_.size(), vals.size());
00324 for (typename Collection::const_iterator it = vals.begin(), ed = vals.end(); it != ed; ++it) {
00325 assoc_.data_.push_back(*it);
00326 }
00327 }
00328
00329 template<typename C>
00330 template<typename KeyRef>
00331 void MultiAssociation<C>::LazyFiller::setValues(const KeyRef &k, const Collection &vals) {
00332 if (k.id() != id_) Indices::throwUnexpectedProductID(k.id(),id_,"LazyFiller::insert");
00333 (*tempValues_)[k.key()] = vals;
00334 }
00335
00336 template<typename C>
00337 template<typename KeyRef>
00338 void MultiAssociation<C>::LazyFiller::swapValues(const KeyRef &k, Collection &vals) {
00339 if (k.id() != id_) Indices::throwUnexpectedProductID(k.id(),id_,"LazyFiller::insert");
00340 vals.swap((*tempValues_)[k.key()]);
00341 }
00342
00343
00344 template<typename C>
00345 void MultiAssociation<C>::LazyFiller::fill() {
00346 if (id_ != ProductID()) {
00347 typename MultiAssociation<C>::FastFiller filler(assoc_, id_, size_);
00348 for (typename TempValues::const_iterator it = tempValues_->begin(), ed = tempValues_->end(); it != ed; ++it) {
00349 filler.setValues(id_, it->first, it->second);
00350 }
00351 id_ = ProductID();
00352 }
00353 }
00354
00355
00356 }
00357
00358 #endif