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