00001 #ifndef DataFormats_Common_RefVectorHolder_h
00002 #define DataFormats_Common_RefVectorHolder_h
00003 #include "DataFormats/Common/interface/RefVectorHolderBase.h"
00004 #include "FWCore/Utilities/interface/EDMException.h"
00005 #include "DataFormats/Provenance/interface/ProductID.h"
00006
00007 namespace edm {
00008 namespace reftobase {
00009 class RefHolderBase;
00010 template <class REF> class RefHolder;
00011
00012 template<typename REFV>
00013 class RefVectorHolder : public RefVectorHolderBase {
00014 public:
00015 RefVectorHolder() { }
00016 RefVectorHolder( const REFV & refs ) : refs_( refs ) { }
00017 virtual ~RefVectorHolder() { }
00018 void swap(RefVectorHolder& other);
00019 RefVectorHolder& operator=(RefVectorHolder const& rhs);
00020 virtual bool empty() const;
00021 virtual size_type size() const;
00022 virtual void clear();
00023 virtual void push_back( const RefHolderBase * r );
00024 virtual void reserve( size_type n );
00025 virtual ProductID id() const;
00026 virtual EDProductGetter const* productGetter() const;
00027 virtual RefVectorHolder<REFV> * clone() const;
00028 virtual RefVectorHolder<REFV> * cloneEmpty() const;
00029 void setRefs( const REFV & refs );
00030 virtual void reallyFillView( const void *, const ProductID &, std::vector<void const*> & );
00031
00032 private:
00033 typedef typename RefVectorHolderBase::const_iterator_imp const_iterator_imp;
00034
00035 public:
00036 struct const_iterator_imp_specific : public const_iterator_imp {
00037 typedef ptrdiff_t difference_type;
00038 const_iterator_imp_specific() { }
00039 explicit const_iterator_imp_specific( const typename REFV::const_iterator & it ) : i ( it ) { }
00040 ~const_iterator_imp_specific() { }
00041 const_iterator_imp_specific * clone() const { return new const_iterator_imp_specific( i ); }
00042 void increase() { ++i; }
00043 void decrease() { --i; }
00044 void increase( difference_type d ) { i += d; }
00045 void decrease( difference_type d ) { i -= d; }
00046 bool equal_to( const const_iterator_imp * o ) const { return i == dc( o ); }
00047 bool less_than( const const_iterator_imp * o ) const { return i < dc( o ); }
00048 void assign( const const_iterator_imp * o ) { i = dc( o ); }
00049 boost::shared_ptr<RefHolderBase> deref() const;
00050 difference_type difference( const const_iterator_imp * o ) const { return i - dc( o ); }
00051 private:
00052 const typename REFV::const_iterator & dc( const const_iterator_imp * o ) const {
00053 if ( o == 0 )
00054 throw edm::Exception( edm::errors::InvalidReference )
00055 << "In RefVectorHolder trying to dereference a null pointer\n";
00056 const const_iterator_imp_specific * oo = dynamic_cast<const const_iterator_imp_specific *>( o );
00057 if ( oo == 0 )
00058 throw edm::Exception( edm::errors::InvalidReference )
00059 << "In RefVectorHolder trying to cast iterator to wrong type\n";
00060 return oo->i;
00061 }
00062 typename REFV::const_iterator i;
00063 };
00064
00065 typedef typename RefVectorHolderBase::const_iterator const_iterator;
00066
00067 const_iterator begin() const {
00068 return const_iterator( new const_iterator_imp_specific( refs_.begin() ) );
00069 }
00070 const_iterator end() const {
00071 return const_iterator( new const_iterator_imp_specific( refs_.end() ) );
00072 }
00073 virtual const void * product() const {
00074 return refs_.product();
00075 }
00076
00079 virtual bool isAvailable() const { return refs_.isAvailable(); }
00080
00081 private:
00082 virtual boost::shared_ptr<reftobase::RefHolderBase> refBase( size_t idx ) const;
00083 REFV refs_;
00084 };
00085
00086
00087
00088
00089
00090 template <typename REFV>
00091 inline
00092 void RefVectorHolder<REFV>::swap(RefVectorHolder<REFV>& other) {
00093 this->RefVectorHolderBase::swap(other);
00094 refs_.swap(other.refs_);
00095 }
00096
00097 template <typename REFV>
00098 inline
00099 RefVectorHolder<REFV>& RefVectorHolder<REFV>::operator=(RefVectorHolder<REFV> const& rhs) {
00100 RefVectorHolder<REFV> temp(rhs);
00101 this->swap(temp);
00102 return *this;
00103 }
00104
00105 template<typename REFV>
00106 inline
00107 bool RefVectorHolder<REFV>::empty() const {
00108 return refs_.empty();
00109 }
00110
00111 template<typename REFV>
00112 inline
00113 typename RefVectorHolder<REFV>::size_type RefVectorHolder<REFV>::size() const {
00114 return refs_.size();
00115 }
00116
00117 template<typename REFV>
00118 inline
00119 void RefVectorHolder<REFV>::clear() {
00120 return refs_.clear();
00121 }
00122
00123 template<typename REFV>
00124 inline
00125 void RefVectorHolder<REFV>::reserve( size_type n ) {
00126 typename REFV::size_type s = n;
00127 refs_.reserve( s );
00128 }
00129
00130 template<typename REFV>
00131 inline
00132 ProductID RefVectorHolder<REFV>::id() const {
00133 return refs_.id();
00134 }
00135
00136 template<typename REFV>
00137 inline
00138 EDProductGetter const* RefVectorHolder<REFV>::productGetter() const {
00139 return refs_.productGetter();
00140 }
00141
00142 template<typename REFV>
00143 inline
00144 RefVectorHolder<REFV> * RefVectorHolder<REFV>::clone() const {
00145 return new RefVectorHolder<REFV>( * this );
00146 }
00147
00148 template<typename REFV>
00149 inline
00150 RefVectorHolder<REFV> * RefVectorHolder<REFV>::cloneEmpty() const {
00151 return new RefVectorHolder<REFV>( id() );
00152 }
00153
00154 template<typename REFV>
00155 inline
00156 void RefVectorHolder<REFV>::setRefs( const REFV & refs ) {
00157 refs_ = refs;
00158 }
00159
00160
00161 template <typename REFV>
00162 inline
00163 void
00164 swap(RefVectorHolder<REFV>& lhs, RefVectorHolder<REFV>& rhs) {
00165 lhs.swap(rhs);
00166 }
00167 }
00168 }
00169
00170 #include "DataFormats/Common/interface/RefHolder.h"
00171
00172 namespace edm {
00173 namespace reftobase {
00174
00175 template<typename REFV>
00176 void RefVectorHolder<REFV>::push_back( const RefHolderBase * h ) {
00177 typedef typename REFV::value_type REF;
00178 const RefHolder<REF> * rh = dynamic_cast<const RefHolder<REF> *>( h );
00179 if( rh == 0 )
00180 throw edm::Exception(errors::InvalidReference)
00181 << "RefVectorHolder: attempting to cast a RefHolderBase "
00182 << "to an invalid type.\nExpected: "
00183 << typeid( REF ).name() << "\n";
00184 refs_.push_back( rh->getRef() );
00185 }
00186
00187 template <class REFV>
00188 boost::shared_ptr<RefHolderBase>
00189 RefVectorHolder<REFV>::refBase(size_t idx) const {
00190 return boost::shared_ptr<RefHolderBase>( new RefHolder<typename REFV::value_type>( refs_[idx] ) );
00191 }
00192
00193 template<typename REFV>
00194 boost::shared_ptr<RefHolderBase> RefVectorHolder<REFV>::const_iterator_imp_specific::deref() const {
00195 return boost::shared_ptr<RefHolderBase>( new RefHolder<typename REFV::value_type>( * i ) );
00196 }
00197
00198 }
00199 }
00200
00201 #include "DataFormats/Common/interface/FillView.h"
00202 #include "DataFormats/Common/interface/traits.h"
00203 #include "boost/mpl/if.hpp"
00204
00205 namespace edm {
00206 namespace reftobase {
00207 template<typename REFV>
00208 struct RefVectorHolderNoFillView {
00209 static void reallyFillView(RefVectorHolder<REFV>&, const void *, const ProductID &, std::vector<void const*> & ) {
00210 throw Exception(errors::ProductDoesNotSupportViews)
00211 << "The product type "
00212 << typeid(typename REFV::collection_type).name()
00213 << "\ndoes not support Views\n";
00214 }
00215 };
00216
00217 template<typename REFV>
00218 struct RefVectorHolderDoFillView {
00219 static void reallyFillView(RefVectorHolder<REFV>& rvh, const void * prod, const ProductID & id , std::vector<void const*> & pointers ) {
00220 typedef typename REFV::collection_type collection;
00221 const collection * product = static_cast<const collection *>( prod );
00222 detail::reallyFillView( * product, id, pointers, rvh );
00223 }
00224 };
00225
00226 template<typename REFV>
00227 void RefVectorHolder<REFV>::reallyFillView( const void * prod, const ProductID & id , std::vector<void const*> & pointers ) {
00228 typedef
00229 typename boost::mpl::if_c<has_fillView<typename REFV::collection_type>::value,
00230 RefVectorHolderDoFillView<REFV>,
00231 RefVectorHolderNoFillView<REFV> >::type maybe_filler;
00232 maybe_filler::reallyFillView( *this, prod, id, pointers );
00233 }
00234 }
00235 }
00236
00237 #endif