Back to home page

Project CMSSW displayed by LXR

 
 

    


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

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