00001 #ifndef DataFormats_Common_AssociationVector_h
00002 #define DataFormats_Common_AssociationVector_h
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "FWCore/Utilities/interface/EDMException.h"
00016
00017 #include "DataFormats/Common/interface/traits.h"
00018 #include "DataFormats/Common/interface/EDProduct.h"
00019 #include "DataFormats/Common/interface/RefProd.h"
00020 #include "DataFormats/Common/interface/RefToBaseProd.h"
00021 #include "DataFormats/Common/interface/Ref.h"
00022 #include "DataFormats/Common/interface/RefToBase.h"
00023 #include "DataFormats/Common/interface/FillView.h"
00024
00025 #include "DataFormats/Provenance/interface/ProductID.h"
00026
00027 #include "boost/static_assert.hpp"
00028 #include "boost/type_traits/is_same.hpp"
00029
00030 namespace edm {
00031 namespace helper {
00032
00033 struct AssociationIdenticalKeyReference {
00034 template<typename T>
00035 static const T & get( const T & t, edm::ProductID ) { return t; }
00036 };
00037
00038 template<typename T>
00039 struct AssociationKeyReferenceTrait {
00040 typedef AssociationIdenticalKeyReference type;
00041 };
00042
00043 template<typename REFPROD>
00044 struct RefFromRefProdTrait { };
00045
00046 template<typename C>
00047 struct RefFromRefProdTrait<RefProd<C> > {
00048 typedef Ref<typename RefProd<C>::product_type> ref_type;
00049 };
00050
00051 template<typename T>
00052 struct RefFromRefProdTrait<RefToBaseProd<T> > {
00053 typedef RefToBase<T> ref_type;
00054 };
00055 }
00056
00057 template<typename KeyRefProd, typename CVal,
00058 typename KeyRef = typename helper::RefFromRefProdTrait<KeyRefProd>::ref_type,
00059 typename SizeType = typename KeyRefProd::product_type::size_type,
00060 typename KeyReferenceHelper = typename helper::AssociationKeyReferenceTrait<KeyRef>::type>
00061 class AssociationVector {
00062 BOOST_STATIC_ASSERT( ( boost::is_same<SizeType, typename CVal::size_type>::value ) );
00063 typedef AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> self;
00064
00065 public:
00066 typedef KeyRefProd refprod_type;
00067 typedef typename KeyRefProd::product_type CKey;
00068 typedef SizeType size_type;
00069 typedef typename KeyRef::value_type key_type;
00070 typedef typename std::pair<KeyRef, typename CVal::value_type> value_type;
00071 typedef std::vector<value_type> transient_vector_type;
00072 typedef const value_type & const_reference;
00073 AssociationVector();
00074 AssociationVector(const KeyRefProd & ref, const CKey * = 0);
00075 AssociationVector(const AssociationVector &);
00076 ~AssociationVector();
00077
00078 size_type size() const;
00079 bool empty() const;
00080 const_reference operator[](size_type n) const;
00081 typename CVal::const_reference operator[](const KeyRef & k) const;
00082 typename CVal::reference operator[](const KeyRef & k);
00083
00084 self & operator=(const self & );
00085
00086 void clear();
00087 void swap(self & other);
00088 const KeyRefProd & keyProduct() const { return ref_; }
00089 KeyRef key(size_type i) const { return KeyRef(ref_, i); }
00090 const typename CVal::value_type value(size_type i) const { return data_[ i ]; }
00091 void setValue(size_type i, const typename CVal::value_type & val );
00092 void fillView(ProductID const& id,
00093 std::vector<void const*>& pointers,
00094 helper_vector& helpers) const;
00095
00096 typedef typename transient_vector_type::const_iterator const_iterator;
00097
00098 const_iterator begin() const { return transientVector().begin(); }
00099 const_iterator end() const { return transientVector().end(); }
00100
00101 private:
00102 CVal data_;
00103 KeyRefProd ref_;
00104 mutable transient_vector_type transientVector_;
00105 mutable bool fixed_;
00106 const transient_vector_type & transientVector() const { fixup(); return transientVector_; }
00107 void fixup() const;
00108 };
00109
00110 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00111 inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::AssociationVector() :
00112 data_(), ref_(), transientVector_(), fixed_(false) { }
00113
00114 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00115 inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::AssociationVector(const KeyRefProd & ref,
00116 const CKey * coll) :
00117 data_(coll == 0 ? ref->size() : coll->size()), ref_(ref),
00118 transientVector_(coll == 0 ? ref->size() : coll->size()), fixed_(true) { }
00119
00120 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00121 inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::
00122 AssociationVector(const AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> & o) :
00123 data_(o.data_), ref_(o.ref_), transientVector_(o.transientVector_), fixed_(o.fixed_) { }
00124
00125 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00126 inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::~AssociationVector() { }
00127
00128 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00129 inline typename AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::const_reference
00130 AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::operator[](size_type n) const {
00131 return transientVector()[ n ];
00132 }
00133
00134 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00135 inline typename CVal::const_reference
00136 AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::operator[]( const KeyRef & k ) const {
00137 KeyRef keyRef = KeyReferenceHelper::get( k, ref_.id() );
00138 if ( keyRef.id() == ref_.id() )
00139 return data_[ keyRef.key() ];
00140 else
00141 throw edm::Exception(edm::errors::InvalidReference)
00142 << "AssociationVector: trying to use [] operator passing a reference"
00143 << " with the wrong product id (i.e.: pointing to the wrong collection)";
00144 }
00145
00146 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00147 inline typename CVal::reference
00148 AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::operator[]( const KeyRef & k ) {
00149 KeyRef keyRef = KeyReferenceHelper::get( k, ref_.id() );
00150 fixed_ = false;
00151 if ( keyRef.id() == ref_.id() )
00152 return data_[ keyRef.key() ];
00153 else
00154 throw edm::Exception(edm::errors::InvalidReference)
00155 << "AssociationVector: trying to use [] operator passing a reference"
00156 << " with the wrong product id (i.e.: pointing to the wrong collection)";
00157 }
00158
00159 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00160 inline AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> &
00161 AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::operator=(const self & o) {
00162 data_ = o.data_;
00163 ref_ = o.ref_;
00164 fixed_ = false;
00165 return * this;
00166 }
00167
00168 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00169 inline void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::setValue(size_type i, const typename CVal::value_type & val ) {
00170 data_[ i ] = val;
00171 KeyRef ref(ref_, i);
00172 transientVector_[ i ].first = ref;
00173 transientVector_[ i ].second = data_[ i ];
00174 }
00175
00176 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00177 inline typename AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::size_type
00178 AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::size() const {
00179 return data_.size();
00180 }
00181
00182 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00183 inline bool AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::empty() const {
00184 return data_.empty();
00185 }
00186
00187 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00188 inline void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::clear() {
00189 data_.clear();
00190 transientVector_.clear();
00191 ref_ = KeyRefProd();
00192 fixed_ = true;
00193 }
00194
00195 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00196 inline void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::swap(self & other) {
00197 data_.swap(other.data_);
00198 transientVector_.swap(other.transientVector_);
00199 ref_.swap( other.ref_);
00200 std::swap(fixed_, other.fixed_);
00201 }
00202
00203 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00204 inline void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::fixup() const {
00205 if (!fixed_) {
00206 fixed_ = true;
00207 transientVector_.resize( size() );
00208 for( size_type i = 0; i != size(); ++ i ) {
00209 transientVector_[ i ] = std::make_pair( KeyRef(ref_, i), data_[ i ] );
00210 }
00211 }
00212 }
00213
00214 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00215 void AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper>::fillView(ProductID const& id,
00216 std::vector<void const*>& pointers,
00217 helper_vector& helpers) const
00218 {
00219 detail::reallyFillView(*this, id, pointers, helpers);
00220
00221
00222
00223
00224
00225 }
00226
00227 template<typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00228 inline void swap(AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> & a,
00229 AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> & b) {
00230 a.swap(b);
00231 }
00232
00233
00234
00235
00236
00237 template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00238 inline
00239 void
00240 fillView(AssociationVector<KeyRefProd,CVal, KeyRef, SizeType, KeyReferenceHelper> const& obj,
00241 ProductID const& id,
00242 std::vector<void const*>& pointers,
00243 helper_vector& helpers) {
00244 obj.fillView(id, pointers, helpers);
00245 }
00246
00247 template <typename KeyRefProd, typename CVal, typename KeyRef, typename SizeType, typename KeyReferenceHelper>
00248 struct has_fillView<edm::AssociationVector<KeyRefProd, CVal, KeyRef, SizeType, KeyReferenceHelper> > {
00249 static bool const value = true;
00250 };
00251
00252 }
00253
00254 #endif