Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:03:52

0001 #ifndef DataFormats_Common_OneToManyWithQualityGeneric_h
0002 #define DataFormats_Common_OneToManyWithQualityGeneric_h
0003 #include "DataFormats/Common/interface/AssociationMapHelpers.h"
0004 #include "DataFormats/Common/interface/Ref.h"
0005 #include "DataFormats/Common/interface/RefProd.h"
0006 #include <functional>
0007 #include <map>
0008 #include <vector>
0009 #include <algorithm>
0010 #include "DataFormats/Common/interface/MapRefViewTrait.h"
0011 
0012 namespace edm {
0013   template <typename CKey,
0014             typename CVal,
0015             typename Q,
0016             typename index = unsigned int,
0017             typename KeyRefProd = typename helper::MapRefViewTrait<CKey>::refprod_type,
0018             typename ValRefProd = typename helper::MapRefViewTrait<CVal>::refprod_type,
0019             typename KeyRef = typename helper::MapRefViewTrait<CKey>::ref_type,
0020             typename ValRef = typename helper::MapRefViewTrait<CVal>::ref_type>
0021   class OneToManyWithQualityGeneric {
0022     /// reference to "key" collection
0023     typedef KeyRefProd keyrefprod_type;
0024     /// reference to "value" collection
0025     typedef ValRefProd valrefprod_type;
0026     /// internal map associated data
0027     typedef std::vector<std::pair<index, Q> > map_assoc;
0028 
0029   public:
0030     /// values reference collection type
0031     typedef std::vector<std::pair<ValRef, Q> > val_type;
0032     /// insert key type
0033     typedef KeyRef key_type;
0034     /// insert val type
0035     typedef std::pair<ValRef, Q> data_type;
0036     /// quality type
0037     typedef Q quality_type;
0038     /// index type
0039     typedef index index_type;
0040     /// map type
0041     typedef std::map<index_type, map_assoc> map_type;
0042     /// reference set type
0043     typedef helpers::KeyVal<keyrefprod_type, valrefprod_type> ref_type;
0044     /// transient map type
0045     typedef std::map<const typename CKey::value_type *, std::vector<std::pair<const typename CVal::value_type *, Q> > >
0046         transient_map_type;
0047     /// transient key vector
0048     typedef std::vector<const typename CKey::value_type *> transient_key_vector;
0049     /// transient val vector
0050     typedef std::vector<std::vector<std::pair<const typename CVal::value_type *, Q> > > transient_val_vector;
0051     /// insert in the map
0052     static void insert(ref_type &ref, map_type &m, const key_type &k, const data_type &v) {
0053       const ValRef &vref = v.first;
0054       if (k.isNull() || vref.isNull())
0055         Exception::throwThis(errors::InvalidReference, "can't insert null references in AssociationMap");
0056       if (ref.key.isNull()) {
0057         if (k.isTransient() || vref.isTransient()) {
0058           Exception::throwThis(errors::InvalidReference,
0059                                "can't insert transient references in uninitialized AssociationMap");
0060         }
0061         //another thread might cause productGetter() to return a different value
0062         EDProductGetter const *getter = ref.key.productGetter();
0063         if (getter == nullptr) {
0064           Exception::throwThis(errors::LogicError,
0065                                "Can't insert into AssociationMap unless it was properly initialized.\n"
0066                                "The most common fix for this is to add arguments to the call to the\n"
0067                                "AssociationMap constructor that are valid Handle's to the containers.\n"
0068                                "If you don't have valid handles or either template parameter to the\n"
0069                                "AssociationMap is a View, then see the comments in AssociationMap.h.\n"
0070                                "(note this was a new requirement added in the 7_5_X release series)\n");
0071         }
0072         ref.key = KeyRefProd(k.id(), getter);
0073         ref.val = ValRefProd(vref.id(), ref.val.productGetter());
0074       }
0075       helpers::checkRef(ref.key, k);
0076       helpers::checkRef(ref.val, vref);
0077       index_type ik = index_type(k.key()), iv = index_type(vref.key());
0078       m[ik].push_back(std::make_pair(iv, v.second));
0079     }
0080     static void insert(ref_type &ref, map_type &m, const key_type &k, const val_type &v) {
0081       for (typename val_type::const_iterator i = v.begin(), iEnd = v.end(); i != iEnd; ++i)
0082         insert(ref, m, k, *i);
0083     }
0084     /// return values collection
0085     static val_type val(const ref_type &ref, const map_assoc &iv) {
0086       val_type v;
0087       for (typename map_assoc::const_iterator idx = iv.begin(), idxEnd = iv.end(); idx != idxEnd; ++idx)
0088         v.push_back(std::make_pair(ValRef(ref.val, idx->first), idx->second));
0089       return v;
0090     }
0091     /// size of data_type
0092     static typename map_type::size_type size(const map_assoc &v) { return v.size(); }
0093 
0094     /// sort
0095     // Note the Framework automatically calls this after putting the object
0096     // into the event using AssociationMap::post_insert. It sorts in reverse
0097     // order of the quality.
0098     static void sort(map_type &m) {
0099       //      using namespace boost::lambda;
0100       for (typename map_type::iterator i = m.begin(), iEnd = m.end(); i != iEnd; ++i) {
0101         using std::placeholders::_1;
0102         using std::placeholders::_2;
0103         map_assoc &v = i->second;
0104         // Q std::pair<index, Q>::*quality = &std::pair<index, Q>::second;
0105         // std::sort(v.begin(), v.end(),
0106         //    bind(quality, boost::lambda::_2) < bind(quality, boost::lambda::_1));
0107         std::sort(v.begin(),
0108                   v.end(),
0109                   std::bind(std::less<Q>(),
0110                             std::bind(&std::pair<index, Q>::second, _2),
0111                             std::bind(&std::pair<index, Q>::second, _1)));
0112       }
0113     }
0114     /// fill transient map
0115     static transient_map_type transientMap(const ref_type &ref, const map_type &map) {
0116       transient_map_type m;
0117       if (!map.empty()) {
0118         const CKey &ckey = *ref.key;
0119         const CVal &cval = *ref.val;
0120         for (typename map_type::const_iterator i = map.begin(); i != map.end(); ++i) {
0121           const map_assoc &a = i->second;
0122           const typename CKey::value_type *k = &ckey[i->first];
0123           std::vector<std::pair<const typename CVal::value_type *, Q> > v;
0124           for (typename map_assoc::const_iterator j = a.begin(); j != a.end(); ++j) {
0125             const typename CVal::value_type *val = &cval[j->first];
0126             v.push_back(std::make_pair(val, j->second));
0127           }
0128           m.insert(std::make_pair(k, v));
0129         }
0130       }
0131       return m;
0132     }
0133     /// fill transient key vector
0134     static transient_key_vector transientKeyVector(const ref_type &ref, const map_type &map) {
0135       transient_key_vector m;
0136       if (!map.empty()) {
0137         const CKey &ckey = *ref.key;
0138         for (typename map_type::const_iterator i = map.begin(); i != map.end(); ++i)
0139           m.push_back(&ckey[i->first]);
0140       }
0141       return m;
0142     }
0143     /// fill transient val vector
0144     static transient_val_vector transientValVector(const ref_type &ref, const map_type &map) {
0145       transient_val_vector m;
0146       if (!map.empty()) {
0147         const CVal &cval = *ref.val;
0148         for (typename map_type::const_iterator i = map.begin(); i != map.end(); ++i) {
0149           const map_assoc &a = i->second;
0150           std::vector<std::pair<const typename CVal::value_type *, Q> > v;
0151           m.push_back(v);
0152           for (typename map_assoc::const_iterator j = a.begin(); j != a.end(); ++j)
0153             m.back().push_back(std::make_pair(&cval[j->first], j->second));
0154         }
0155       }
0156       return m;
0157     }
0158   };
0159 }  // namespace edm
0160 
0161 #endif