Association

Filler

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
#ifndef DataFormats_Common_Association_h
#define DataFormats_Common_Association_h
/* \class Association<RefProd>
 *
 * \author Luca Lista, INFN
 *
 *
 */

#include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
#include "DataFormats/Common/interface/Ref.h"
#include "DataFormats/Common/interface/RefProd.h"
#include "DataFormats/Common/interface/ValueMap.h"

namespace edm {

  template <typename C>
  class Association : private ValueMap<int> {
  public:
    typedef int index;  // negative index == null reference
    typedef ValueMap<index> base;
    typedef typename base::offset offset;
    typedef edm::RefProd<C> refprod_type;  // could be specialized for View
    typedef Ref<typename refprod_type::product_type> reference_type;

    Association() : base() {}
    template <typename H>
    explicit Association(const H& h) : base(), ref_(h) {}

    // import this function from ValueMap<int>
    using base::rawIndexOf;

    template <typename RefKey>
    reference_type operator[](const RefKey& r) const {
      return get(r.id(), r.key());
    }

    /// meant to be used internally or in AssociativeIterator, not by the ordinary user
    reference_type get(size_t rawIdx) const {
      index i = values_[rawIdx];
      if (i < 0)
        return reference_type();
      size_t k = i;
      if (k >= ref_->size())
        throwIndexMapBound();
      return reference_type(ref_, k);
    }

    reference_type get(ProductID id, size_t idx) const { return get(rawIndexOf(id, idx)); }

    Association<C>& operator+=(const Association<C>& o) {
      add(o);
      return *this;
    }
    void setRef(const refprod_type& ref) {
      if (ref_.isNull()) {
        ref_ = ref;
      } else {
        if (ref_.id() != ref.id())
          throwRefSet();
      }
    }
    bool contains(ProductID id) const { return base::contains(id); }
    size_t size() const { return base::size(); }
    bool empty() const { return base::empty(); }
    void clear() { base::clear(); }
    refprod_type ref() const { return ref_; }
    void swap(Association& other) {
      this->ValueMap<int>::swap(other);
      ref_.swap(other.ref_);
    }

    class Filler : public helper::Filler<Association<C> > {
      typedef helper::Filler<Association<C> > base;

    public:
      explicit Filler(Association<C>& association) : base(association) {}
      void add(const Association<C>& association) {
        base::map_.setRef(association.ref());
        base::add(association);
      }
    };

    /// meant to be used in AssociativeIterator, not by the ordinary user
    const id_offset_vector& ids() const { return ids_; }
    /// meant to be used in AssociativeIterator, not by the ordinary user
    using base::id_offset_vector;

    //Used by ROOT storage
    CMS_CLASS_VERSION(10)

  private:
    refprod_type ref_;
    void throwIndexMapBound() const {
      Exception::throwThis(errors::InvalidReference, "Association: index in the map out of upper boundary\n");
    }
    void throwRefSet() const {
      Exception::throwThis(errors::InvalidReference, "Association: reference to product already set\n");
    }

    void add(const Association<C>& o) {
      Filler filler(*this);
      filler.add(o);
      filler.fill();
    }

    friend class helper::Filler<Association<C> >;
  };

  // Free swap function
  template <typename C>
  inline void swap(Association<C>& lhs, Association<C>& rhs) {
    lhs.swap(rhs);
  }

  template <typename C>
  inline Association<C> operator+(const Association<C>& a1, const Association<C>& a2) {
    Association<C> a = a1;
    a += a2;
    return a;
  }
}  // namespace edm

#endif