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.8 2009/11/04 15:30:19 wmtan 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 Exception::throwThis(errors::InvalidReference, "Association: index in the map out of upper boundary\n"); 00096 } 00097 void throwRefSet() const { 00098 Exception::throwThis(errors::InvalidReference, "Association: reference to product already set\n"); 00099 } 00100 00101 void add( const Association<C> & o ) { 00102 Filler filler(*this); 00103 filler.add(o); 00104 filler.fill(); 00105 } 00106 00107 friend class helper::Filler<Association<C> >; 00108 }; 00109 00110 // Free swap function 00111 template <typename C> 00112 inline void swap(Association<C>& lhs, Association<C>& rhs) { 00113 lhs.swap(rhs); 00114 } 00115 00116 template<typename C> 00117 inline Association<C> operator+( const Association<C> & a1, 00118 const Association<C> & a2 ) { 00119 Association<C> a = a1; 00120 a += a2; 00121 return a; 00122 } 00123 } 00124 00125 #endif