CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_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=(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     // Find should be private!  However, generated reflex dictionaries do not compile
00139     //  with gcc 3.4.5 if Find is private.  Reflex should fix this!!
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     //Used by ROOT storage
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