CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/DataFormats/Common/interface/AssociationMap.h

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/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(): map_(0) { }
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     // Find should be private!  However, generated reflex dictionaries do not compile
00138     //  with gcc 3.4.5 if Find is private.  Reflex should fix this!!
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           Exception::throwThis(edm::errors::InvalidReference, "can't find reference in AssociationMap at position ", i);
00169         value_type v(key_type(ref_.key, i), Tag::val(ref_, f->second));
00170         std::pair<typename internal_transient_map_type::const_iterator, bool> ins =
00171           transientMap_.insert(std::make_pair(i, v));
00172         return ins.first->second;
00173       } else {
00174         return tf->second;
00175       }
00176     }
00177     friend struct const_iterator;
00178     friend struct Find;
00179     friend struct refhelper::FindTrait<self,value_type>;
00180     template<typename, typename, typename> friend class OneToValue;
00181     template<typename, typename, typename> friend class OneToOne;
00182     template<typename, typename, typename> friend class OneToMany;
00183     template<typename, typename, typename, typename> friend class OneToManyWithQuality;
00184   };
00185 
00186   namespace refhelper {
00187     template<typename Tag>
00188     struct FindTrait<AssociationMap<Tag>,
00189                      typename AssociationMap<Tag>::value_type> {
00190       typedef typename AssociationMap<Tag>::Find value;
00191     };
00192   }
00193 
00194 }
00195 
00196 #endif