Go to the documentation of this file.00001 #ifndef DataFormats_Common_AssociationMap_h
00002 #define DataFormats_Common_AssociationMap_h
00003
00012 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00013 #include "DataFormats/Common/interface/RefVector.h"
00014 #include "DataFormats/Common/interface/OneToValue.h"
00015 #include "DataFormats/Common/interface/OneToOne.h"
00016 #include "DataFormats/Common/interface/OneToMany.h"
00017 #include "DataFormats/Common/interface/OneToManyWithQuality.h"
00018
00019 namespace edm {
00020 template<typename Tag>
00021 class AssociationMap {
00023 typedef typename Tag::val_type internal_val_type;
00024 public:
00026 typedef AssociationMap<Tag> self;
00028 typedef typename Tag::index_type index_type;
00030 typedef typename Tag::key_type key_type;
00032 typedef typename Tag::data_type data_type;
00034 typedef typename Tag::ref_type ref_type;
00036 typedef typename Tag::map_type map_type;
00038 typedef typename map_type::size_type size_type;
00040 typedef helpers::KeyVal<key_type, internal_val_type> value_type;
00042 typedef typename value_type::value_type result_type;
00044 typedef typename std::map<index_type, value_type> internal_transient_map_type;
00045
00047 struct const_iterator {
00048 typedef typename self::value_type value_type;
00049 typedef ptrdiff_t difference_type;
00050 typedef value_type * pointer;
00051 typedef value_type & reference;
00052 typedef typename map_type::const_iterator::iterator_category iterator_category;
00053 const_iterator(): map_(0) { }
00054 const_iterator(const self * map, typename map_type::const_iterator mi) :
00055 map_(map), i(mi) { }
00056 const_iterator & operator=(const const_iterator & it) {
00057 map_ = it.map_; i = it.i; return *this;
00058 }
00059 const_iterator& operator++() { ++i; return *this; }
00060 const_iterator operator++(int) { const_iterator ci = *this; ++i; return ci; }
00061 const_iterator& operator--() { --i; return *this; }
00062 const_iterator operator--(int) { const_iterator ci = *this; --i; return ci; }
00063 bool operator==(const const_iterator& ci) const { return i == ci.i; }
00064 bool operator!=(const const_iterator& ci) const { return i != ci.i; }
00065 const value_type & operator *() const { return (*map_)[ i->first ]; }
00066 const value_type * operator->() const { return &operator *(); }
00067 private:
00068 const self * map_;
00069 typename map_type::const_iterator i;
00070 };
00071
00073 AssociationMap() { }
00075 explicit
00076 AssociationMap(const ref_type & ref) : ref_(ref) { }
00078 void clear() { map_.clear(); transientMap_.clear(); }
00080 size_type size() const { return map_.size(); }
00082 bool empty() const { return map_.empty(); }
00084 void insert(const key_type & k, const data_type & v) {
00085 Tag::insert(ref_, map_, k, v);
00086 }
00087 void insert(const value_type & kv) {
00088 Tag::insert(ref_, map_, kv.key, kv.val);
00089 }
00091 const_iterator begin() const { return const_iterator(this, map_.begin()); }
00093 const_iterator end() const { return const_iterator(this, map_.end()); }
00095 const_iterator find(const key_type & k) const {
00096 if (ref_.key.id() != k.id()) return end();
00097 return find(k.key());
00098 }
00100 size_type erase(const key_type& k) {
00101 index_type i = k.key();
00102 transientMap_.erase(i);
00103 return map_.erase(i);
00104 }
00106 const result_type & operator[](const key_type & k) const {
00107 helpers::checkRef(ref_.key, k);
00108 return operator[](k.key()).val;
00109 }
00111 size_type numberOfAssociations(const key_type & k) const {
00112 if (ref_.key.id() != k.id()) return 0;
00113 typename map_type::const_iterator f = map_.find(k.key());
00114 if (f == map_.end()) return 0;
00115 return Tag::size(f->second);
00116 }
00118 const ref_type & refProd() const { return ref_; }
00119
00122 typename Tag::transient_map_type map() {
00123 return Tag::transientMap( ref_, map_ );
00124 }
00127 typename Tag::transient_key_vector keys() {
00128 return Tag::transientKeyVector( ref_, map_ );
00129 }
00132 typename Tag::transient_val_vector values() {
00133 return Tag::transientValVector( ref_, map_ );
00134 }
00136 void post_insert() { Tag::sort(map_); }
00137
00138
00139
00141 struct Find :
00142 public std::binary_function<const self&, size_type, const value_type *> {
00143 typedef Find self;
00144 const value_type * operator()(typename self::first_argument_type c,
00145 typename self::second_argument_type i) {
00146 return &(*c.find(i));
00147 }
00148 };
00149
00150
00151 CMS_CLASS_VERSION(10)
00152
00153 private:
00155 ref_type ref_;
00157 map_type map_;
00159 mutable internal_transient_map_type transientMap_;
00161 const_iterator find(size_type i) const {
00162 typename map_type::const_iterator f = map_.find(i);
00163 if (f == map_.end()) return end();
00164 return const_iterator(this, f);
00165 }
00167 const value_type & operator[](size_type i) const {
00168 typename internal_transient_map_type::const_iterator tf = transientMap_.find(i);
00169 if (tf == transientMap_.end()) {
00170 typename map_type::const_iterator f = map_.find(i);
00171 if (f == map_.end())
00172 Exception::throwThis(edm::errors::InvalidReference, "can't find reference in AssociationMap at position ", i);
00173 value_type v(key_type(ref_.key, i), Tag::val(ref_, f->second));
00174 std::pair<typename internal_transient_map_type::const_iterator, bool> ins =
00175 transientMap_.insert(std::make_pair(i, v));
00176 return ins.first->second;
00177 } else {
00178 return tf->second;
00179 }
00180 }
00181 friend struct const_iterator;
00182 friend struct Find;
00183 friend struct refhelper::FindTrait<self,value_type>;
00184 template<typename, typename, typename> friend class OneToValue;
00185 template<typename, typename, typename> friend class OneToOne;
00186 template<typename, typename, typename> friend class OneToMany;
00187 template<typename, typename, typename, typename> friend class OneToManyWithQuality;
00188 };
00189
00190 namespace refhelper {
00191 template<typename Tag>
00192 struct FindTrait<AssociationMap<Tag>,
00193 typename AssociationMap<Tag>::value_type> {
00194 typedef typename AssociationMap<Tag>::Find value;
00195 };
00196 }
00197
00198 }
00199
00200 #endif