00001 #ifndef DataFormats_Common_AssociationMap_h
00002 #define DataFormats_Common_AssociationMap_h
00003
00012 #include "DataFormats/Common/interface/RefVector.h"
00013 #include "DataFormats/Common/interface/OneToValue.h"
00014 #include "DataFormats/Common/interface/OneToOne.h"
00015 #include "DataFormats/Common/interface/OneToMany.h"
00016 #include "DataFormats/Common/interface/OneToManyWithQuality.h"
00017
00018 namespace edm {
00019 template<typename Tag>
00020 class AssociationMap {
00022 typedef typename Tag::val_type internal_val_type;
00023 public:
00025 typedef AssociationMap<Tag> self;
00027 typedef typename Tag::index_type index_type;
00029 typedef typename Tag::key_type key_type;
00031 typedef typename Tag::data_type data_type;
00033 typedef typename Tag::ref_type ref_type;
00035 typedef typename Tag::map_type map_type;
00037 typedef typename map_type::size_type size_type;
00039 typedef helpers::KeyVal<key_type, internal_val_type> value_type;
00041 typedef typename value_type::value_type result_type;
00043 typedef typename std::map<index_type, value_type> internal_transient_map_type;
00044
00046 struct const_iterator {
00047 typedef typename self::value_type value_type;
00048 typedef ptrdiff_t difference_type;
00049 typedef value_type * pointer;
00050 typedef value_type & reference;
00051 typedef typename map_type::const_iterator::iterator_category iterator_category;
00052 const_iterator() { }
00053 const_iterator(const self * map, typename map_type::const_iterator mi) :
00054 map_(map), i(mi) { }
00055 const_iterator & operator=(const const_iterator & it) {
00056 map_ = it.map_; i = it.i; return *this;
00057 }
00058 const_iterator& operator++() { ++i; return *this; }
00059 const_iterator operator++(int) { const_iterator ci = *this; ++i; return ci; }
00060 const_iterator& operator--() { --i; return *this; }
00061 const_iterator operator--(int) { const_iterator ci = *this; --i; return ci; }
00062 bool operator==(const const_iterator& ci) const { return i == ci.i; }
00063 bool operator!=(const const_iterator& ci) const { return i != ci.i; }
00064 const value_type & operator *() const { return (*map_)[ i->first ]; }
00065 const value_type * operator->() const { return &operator *(); }
00066 private:
00067 const self * map_;
00068 typename map_type::const_iterator i;
00069 };
00070
00072 AssociationMap() { }
00074 explicit
00075 AssociationMap(const ref_type & ref) : ref_(ref) { }
00077 void clear() { map_.clear(); transientMap_.clear(); }
00079 size_type size() const { return map_.size(); }
00081 bool empty() const { return map_.empty(); }
00083 void insert(const key_type & k, const data_type & v) {
00084 Tag::insert(ref_, map_, k, v);
00085 }
00086 void insert(const value_type & kv) {
00087 Tag::insert(ref_, map_, kv.key, kv.val);
00088 }
00090 const_iterator begin() const { return const_iterator(this, map_.begin()); }
00092 const_iterator end() const { return const_iterator(this, map_.end()); }
00094 const_iterator find(const key_type & k) const {
00095 if (ref_.key.id() != k.id()) return end();
00096 return find(k.key());
00097 }
00099 size_type erase(const key_type& k) {
00100 index_type i = k.key();
00101 transientMap_.erase(i);
00102 return map_.erase(i);
00103 }
00105 const result_type & operator[](const key_type & k) const {
00106 helpers::checkRef(ref_.key, k);
00107 return operator[](k.key()).val;
00108 }
00110 size_type numberOfAssociations(const key_type & k) const {
00111 if (ref_.key.id() != k.id()) return 0;
00112 typename map_type::const_iterator f = map_.find(k.key());
00113 if (f == map_.end()) return 0;
00114 return Tag::size(f->second);
00115 }
00117 const ref_type & refProd() const { return ref_; }
00118
00121 typename Tag::transient_map_type map() {
00122 return Tag::transientMap( ref_, map_ );
00123 }
00126 typename Tag::transient_key_vector keys() {
00127 return Tag::transientKeyVector( ref_, map_ );
00128 }
00131 typename Tag::transient_val_vector values() {
00132 return Tag::transientValVector( ref_, map_ );
00133 }
00135 void post_insert() { Tag::sort(map_); }
00136
00137
00138
00140 struct Find :
00141 public std::binary_function<const self&, size_type, const value_type *> {
00142 typedef Find self;
00143 const value_type * operator()(typename self::first_argument_type c,
00144 typename self::second_argument_type i) {
00145 return &(*c.find(i));
00146 }
00147 };
00148
00149 private:
00151 ref_type ref_;
00153 map_type map_;
00155 mutable internal_transient_map_type transientMap_;
00157 const_iterator find(size_type i) const {
00158 typename map_type::const_iterator f = map_.find(i);
00159 if (f == map_.end()) return end();
00160 return const_iterator(this, f);
00161 }
00163 const value_type & operator[](size_type i) const {
00164 typename internal_transient_map_type::const_iterator tf = transientMap_.find(i);
00165 if (tf == transientMap_.end()) {
00166 typename map_type::const_iterator f = map_.find(i);
00167 if (f == map_.end())
00168 throw edm::Exception(edm::errors::InvalidReference)
00169 << "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