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