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++() { ++i; return *this; }
00057 const_iterator operator++(int) { const_iterator ci = *this; ++i; return ci; }
00058 const_iterator& operator--() { --i; return *this; }
00059 const_iterator operator--(int) { const_iterator ci = *this; --i; return ci; }
00060 bool operator==(const const_iterator& ci) const { return i == ci.i; }
00061 bool operator!=(const const_iterator& ci) const { return i != ci.i; }
00062 const value_type & operator *() const { return (*map_)[ i->first ]; }
00063 const value_type * operator->() const { return &operator *(); }
00064 private:
00065 const self * map_;
00066 typename map_type::const_iterator i;
00067 };
00068
00070 AssociationMap() { }
00072 explicit
00073 AssociationMap(const ref_type & ref) : ref_(ref) { }
00075 void clear() { map_.clear(); transientMap_.clear(); }
00077 size_type size() const { return map_.size(); }
00079 bool empty() const { return map_.empty(); }
00081 void insert(const key_type & k, const data_type & v) {
00082 Tag::insert(ref_, map_, k, v);
00083 }
00084 void insert(const value_type & kv) {
00085 Tag::insert(ref_, map_, kv.key, kv.val);
00086 }
00088 const_iterator begin() const { return const_iterator(this, map_.begin()); }
00090 const_iterator end() const { return const_iterator(this, map_.end()); }
00092 const_iterator find(const key_type & k) const {
00093 if (ref_.key.id() != k.id()) return end();
00094 return find(k.key());
00095 }
00097 size_type erase(const key_type& k) {
00098 index_type i = k.key();
00099 transientMap_.erase(i);
00100 return map_.erase(i);
00101 }
00103 const result_type & operator[](const key_type & k) const {
00104 helpers::checkRef(ref_.key, k);
00105 return operator[](k.key()).val;
00106 }
00108 size_type numberOfAssociations(const key_type & k) const {
00109 if (ref_.key.id() != k.id()) return 0;
00110 typename map_type::const_iterator f = map_.find(k.key());
00111 if (f == map_.end()) return 0;
00112 return Tag::size(f->second);
00113 }
00115 const ref_type & refProd() const { return ref_; }
00116
00119 typename Tag::transient_map_type map() {
00120 return Tag::transientMap( ref_, map_ );
00121 }
00124 typename Tag::transient_key_vector keys() {
00125 return Tag::transientKeyVector( ref_, map_ );
00126 }
00129 typename Tag::transient_val_vector values() {
00130 return Tag::transientValVector( ref_, map_ );
00131 }
00133 void post_insert() { Tag::sort(map_); }
00134
00135
00136
00138 struct Find :
00139 public std::binary_function<const self&, size_type, const value_type *> {
00140 typedef Find self;
00141 const value_type * operator()(typename self::first_argument_type c,
00142 typename self::second_argument_type i) {
00143 return &(*c.find(i));
00144 }
00145 };
00146
00147
00148 CMS_CLASS_VERSION(10)
00149
00150 private:
00152 ref_type ref_;
00154 map_type map_;
00156 mutable internal_transient_map_type transientMap_;
00158 const_iterator find(size_type i) const {
00159 typename map_type::const_iterator f = map_.find(i);
00160 if (f == map_.end()) return end();
00161 return const_iterator(this, f);
00162 }
00164 const value_type & operator[](size_type i) const {
00165 typename internal_transient_map_type::const_iterator tf = transientMap_.find(i);
00166 if (tf == transientMap_.end()) {
00167 typename map_type::const_iterator f = map_.find(i);
00168 if (f == map_.end())
00169 Exception::throwThis(edm::errors::InvalidReference, "can't find reference in AssociationMap at position ", i);
00170 value_type v(key_type(ref_.key, i), Tag::val(ref_, f->second));
00171 std::pair<typename internal_transient_map_type::const_iterator, bool> ins =
00172 transientMap_.insert(std::make_pair(i, v));
00173 return ins.first->second;
00174 } else {
00175 return tf->second;
00176 }
00177 }
00178 friend struct const_iterator;
00179 friend struct Find;
00180 friend struct refhelper::FindTrait<self,value_type>;
00181 template<typename, typename, typename> friend class OneToValue;
00182 template<typename, typename, typename> friend class OneToOne;
00183 template<typename, typename, typename> friend class OneToMany;
00184 template<typename, typename, typename, typename> friend class OneToManyWithQuality;
00185 };
00186
00187 namespace refhelper {
00188 template<typename Tag>
00189 struct FindTrait<AssociationMap<Tag>,
00190 typename AssociationMap<Tag>::value_type> {
00191 typedef typename AssociationMap<Tag>::Find value;
00192 };
00193 }
00194
00195 }
00196
00197 #endif