00001 #ifndef DataFormats_Common_AssociativeIterator_h
00002 #define DataFormats_Common_AssociativeIterator_h
00003
00042 #include "DataFormats/Provenance/interface/ProductID.h"
00043 #include <DataFormats/Common/interface/EDProductGetter.h>
00044
00045 namespace edm {
00046 struct Event;
00047 template <class T> struct View;
00048 template <class T> struct Handle;
00049 template <class T> struct Association;
00050 template <class T> struct RefToBase;
00051 template <class T> struct Ptr;
00052 template <class C, class T, class F> struct Ref;
00053 }
00054
00055 namespace edm {
00056
00057
00058
00059
00060 namespace helper {
00061 template<typename RefFrom, typename RefTo>
00062 struct RefConverter {
00063 static RefTo convert(const RefFrom &ref) { return RefTo(ref); }
00064 };
00065 template<typename T>
00066 struct RefConverter<RefToBase<T>, Ptr<T> > {
00067 static Ptr<T> convert(const RefToBase<T> &ref) { return Ptr<T>(ref.id(), ref.isAvailable() ? ref.get() : 0, ref.key()); }
00068 };
00069 template<typename T, typename C, typename V, typename F>
00070 struct RefConverter<RefToBase<T>, Ref<C,V,F> > {
00071 static Ref<C,V,F> convert(const RefToBase<T> &ref) { return ref.template castTo<Ref<C,V,F> >(); }
00072 };
00073 }
00074
00076
00077 template<typename RefType>
00078 class EdmEventItemGetter {
00079 public:
00080 typedef typename RefType::value_type element_type;
00081 EdmEventItemGetter(const edm::Event &iEvent) : iEvent_(iEvent) { }
00082 ~EdmEventItemGetter() { }
00083
00084 RefType get(const ProductID &id, size_t idx) const {
00085 typedef typename edm::RefToBase<element_type> BaseRefType;
00086 if (id_ != id) {
00087 id_ = id;
00088 iEvent_.get(id_, view_);
00089 }
00090 BaseRefType ref = view_->refAt(idx);
00091 typedef typename helper::RefConverter<BaseRefType, RefType> conv;
00092 return conv::convert(ref);
00093 }
00094 private:
00095 mutable Handle<View<element_type> > view_;
00096 mutable ProductID id_;
00097 const edm::Event &iEvent_;
00098 };
00099
00100
00101
00102 namespace helper {
00103 template<typename AC>
00104 struct AssociativeCollectionValueType {
00105 typedef typename AC::value_type type;
00106 };
00107
00108 template<typename C>
00109 struct AssociativeCollectionValueType< Association<C> > {
00110 typedef typename Association<C>::reference_type type;
00111 };
00112 }
00113
00114 template<typename KeyRefType, typename AssociativeCollection,
00115 typename ItemGetter = EdmEventItemGetter<KeyRefType> >
00116 class AssociativeIterator {
00117 public:
00118 typedef KeyRefType key_type;
00119 typedef typename KeyRefType::value_type key_val_type;
00120 typedef typename helper::AssociativeCollectionValueType<AssociativeCollection>::type val_type;
00121 typedef typename std::pair<key_type, val_type> value_type;
00122
00123 typedef AssociativeIterator<KeyRefType,AssociativeCollection,ItemGetter> self_type;
00124
00126 AssociativeIterator(const AssociativeCollection &map, const ItemGetter &getter) ;
00127
00128 self_type & operator++() ;
00129 self_type & operator--() ;
00130 self_type & nextProductID() ;
00131
00132
00133 const value_type & operator*() const { return *(this->get()); }
00134 const value_type * operator->() const { return (this->get()); }
00135 const value_type * get() const { chkPair(); return & pair_; }
00136
00137 const key_type & key() const { chkPair(); return pair_.first; }
00138 const val_type & val() const { return map_.get(idx_); }
00139 const ProductID & id() const { return ioi_->first; }
00140
00141 operator bool() const { return idx_ < map_.size(); }
00142 self_type end() const ;
00143
00144 bool operator==(const self_type &other) const { return other.idx_ == idx_; }
00145 bool operator!=(const self_type &other) const { return other.idx_ != idx_; }
00146 bool operator<( const self_type &other) const { return other.idx_ < idx_; }
00147
00148 private:
00149 typedef typename AssociativeCollection::id_offset_vector id_offset_vector;
00150 typedef typename id_offset_vector::const_iterator id_offset_iterator;
00151 const AssociativeCollection & map_;
00152 id_offset_iterator ioi_, ioi2_;
00153 size_t idx_;
00154
00155 ItemGetter getter_;
00156
00157 mutable bool pairOk_;
00158 mutable value_type pair_;
00159
00160 void chkPair() const ;
00161
00162 };
00163
00164 template<typename KeyRefType, typename AC, typename IG>
00165 AssociativeIterator<KeyRefType,AC,IG>::AssociativeIterator(const AC &map, const IG &getter) :
00166 map_(map), ioi_(map_.ids().begin()), ioi2_(ioi_+1), idx_(0),
00167 getter_(getter),
00168 pairOk_(false)
00169 {
00170 }
00171
00172 template<typename KeyRefType, typename AC, typename IG>
00173 AssociativeIterator<KeyRefType,AC,IG> & AssociativeIterator<KeyRefType,AC,IG>::operator++() {
00174 pairOk_ = false;
00175 idx_++;
00176 if (ioi2_ < map_.ids().end()) {
00177 if (ioi2_->second == idx_) {
00178 ++ioi_; ++ioi2_;
00179 }
00180 }
00181 return *this;
00182 }
00183
00184 template<typename KeyRefType, typename AC, typename IG>
00185 AssociativeIterator<KeyRefType,AC,IG> & AssociativeIterator<KeyRefType,AC,IG>::operator--() {
00186 pairOk_ = false;
00187 idx_--;
00188 if (ioi_->second < idx_) {
00189 --ioi_; --ioi2_;
00190 }
00191 return *this;
00192
00193 }
00194
00195 template<typename KeyRefType, typename AC, typename IG>
00196 AssociativeIterator<KeyRefType,AC,IG> & AssociativeIterator<KeyRefType,AC,IG>::nextProductID() {
00197 pairOk_ = false;
00198 ioi_++; ioi2_++;
00199 if (ioi_ == map_.ids().end()) {
00200 idx_ = map_.size();
00201 } else {
00202 idx_ = ioi_->second;
00203 }
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 template<typename KeyRefType, typename AC, typename IG>
00215 AssociativeIterator<KeyRefType,AC,IG> AssociativeIterator<KeyRefType,AC,IG>::end() const {
00216 self_type ret(map_, getter_);
00217 ret.ioi_ = map_.ids().end();
00218 ret.ioi2_ = ret.ioi_ + 1;
00219 ret.idx_ = map_.size();
00220 return ret;
00221 }
00222
00223 template<typename KeyRefType, typename AC, typename IG>
00224 void AssociativeIterator<KeyRefType,AC,IG>::chkPair() const {
00225 if (pairOk_) return;
00226 pair_.first = getter_.get(id(), idx_ - ioi_->second);
00227 pair_.second = map_.get(idx_);
00228 pairOk_ = true;
00229 }
00230
00231 }
00232
00233 #endif
00234