CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_13_patch3/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/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     // Find should be private!  However, generated reflex dictionaries do not compile
00136     //  with gcc 3.4.5 if Find is private.  Reflex should fix this!!
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     //Used by ROOT storage
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