CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/DataFormats/Common/interface/Association.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_Association_h
00002 #define DataFormats_Common_Association_h
00003 /* \class Association<RefProd>
00004  *
00005  * \author Luca Lista, INFN
00006  *
00007  * \version $Id: Association.h,v 1.9 2011/03/08 18:47:15 chrjones Exp $
00008  *
00009  */
00010 
00011 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00012 #include "DataFormats/Common/interface/Ref.h"
00013 #include "DataFormats/Common/interface/RefProd.h"
00014 #include "DataFormats/Common/interface/ValueMap.h"
00015 
00016 namespace edm {
00017   
00018   template<typename C>
00019   class Association : private ValueMap<int> {
00020   public:
00021     typedef int index; // negative index == null reference
00022     typedef ValueMap<index> base;
00023     typedef typename base::offset offset;
00024     typedef edm::RefProd<C> refprod_type; // could be specialized for View
00025     typedef Ref<typename refprod_type::product_type> reference_type;
00026 
00027     Association() : base() { }
00028     template<typename H>
00029     explicit Association(const H & h) : base(), ref_(h) { }
00030 
00031     // import this function from ValueMap<int>
00032     using base::rawIndexOf;
00033  
00034     template<typename RefKey>
00035       reference_type operator[](const RefKey & r) const {
00036       return get(r.id(), r.key());
00037     }
00038 
00040     reference_type get(size_t rawIdx) const { 
00041       index i = values_[rawIdx];
00042       if(i < 0) return reference_type(); 
00043       size_t k = i;
00044       if (k >= ref_->size()) throwIndexMapBound();
00045       return reference_type(ref_,k);
00046     }
00047 
00048     reference_type get(ProductID id, size_t idx) const { 
00049       return get(rawIndexOf(id,idx));
00050     }
00051 
00052     Association<C> & operator+=(const Association<C> & o) {
00053       add(o);
00054       return *this;
00055     }
00056     void setRef(const refprod_type & ref) {
00057       if(ref_.isNull() ) {
00058         ref_ = ref;
00059       } else {
00060         if(ref_.id() != ref.id()) throwRefSet();
00061       }
00062     }
00063     bool contains(ProductID id) const { return base::contains(id); }
00064     size_t size() const { return base::size(); }
00065     bool empty() const { return base::empty(); }
00066     void clear() { base::clear(); }
00067     refprod_type ref() const { return ref_; }
00068     void swap(Association& other) {
00069       this->ValueMap<int>::swap(other);
00070       ref_.swap(other.ref_);
00071     }
00072     Association& operator=(Association const& rhs) {
00073       Association temp(rhs);
00074       this->swap(temp);
00075       return *this;
00076     }
00077 
00078     class Filler : public helper::Filler<Association<C> > {
00079       typedef helper::Filler<Association<C> > base;
00080     public:
00081       explicit Filler(Association<C> & association) : 
00082         base(association) { }
00083       void add(const Association<C> & association) {
00084         base::map_.setRef(association.ref());
00085         base::add(association);
00086       }
00087     };
00088 
00090     const id_offset_vector & ids() const { return ids_; }
00092     using base::id_offset_vector;
00093     
00094     //Used by ROOT storage
00095     CMS_CLASS_VERSION(10)
00096 
00097   private:
00098     refprod_type ref_;
00099     void throwIndexMapBound() const {
00100       Exception::throwThis(errors::InvalidReference, "Association: index in the map out of upper boundary\n");
00101     }
00102     void throwRefSet() const {
00103       Exception::throwThis(errors::InvalidReference, "Association: reference to product already set\n");
00104     }
00105 
00106     void add( const Association<C> & o ) {
00107       Filler filler(*this);
00108       filler.add(o);
00109       filler.fill();
00110     }
00111 
00112     friend class helper::Filler<Association<C> >;
00113   }; 
00114   
00115   // Free swap function
00116   template <typename C>
00117   inline void swap(Association<C>& lhs, Association<C>& rhs) {
00118     lhs.swap(rhs);
00119   }
00120 
00121   template<typename C>
00122   inline  Association<C> operator+( const Association<C> & a1,
00123                                        const Association<C> & a2 ) {
00124     Association<C> a = a1;
00125     a += a2;
00126     return a;
00127   }
00128 }
00129 
00130 #endif