CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/PhysicsTools/PatUtils/interface/RefHelper.h

Go to the documentation of this file.
00001 #ifndef PhysicsTools_PatUtils_RefHelper_h
00002 #define PhysicsTools_PatUtils_RefHelper_h
00003 
00004 #include "DataFormats/Common/interface/Ptr.h"
00005 #include "DataFormats/Common/interface/ValueMap.h"
00006 namespace pat { namespace helper {
00007 /*** \brief A class to help manage references and associative containers in some tricky cases (e.g.  selection by copy)
00008 */
00009 template<typename T>
00010 class RefHelper {
00011     public:
00012         typedef typename edm::Ptr<T> Ref;
00013 
00015         RefHelper(const edm::ValueMap< Ref > &backRefMap) : backRefMap_(backRefMap) { }
00016 
00018         Ref parentOrNull(const Ref &ref) const ;
00019 
00021         Ref parentOrSelf(const Ref &ref) const ;
00022 
00024         Ref ancestorOrSelf(const Ref &ref) const ;
00025 
00026         bool isRoot(const Ref &ref) const ;
00027 
00029         bool isAncestorOf(const Ref &old, const Ref &young) const ;
00030 
00032         bool sharedAncestor(const Ref &ref1, const Ref &ref2) const ;
00033 
00036         template<typename V, typename SomeRef>
00037         V recursiveLookup(const SomeRef &ref, const edm::ValueMap<V> &map) const ;
00038 
00041         template<typename V, typename SomeRef>
00042         V ancestorLookup(const SomeRef &ref, const edm::ValueMap<V> &map) const ;
00043 
00044     private:
00045         const edm::ValueMap< Ref > & backRefMap_;
00046 };
00047 
00048 template<typename T>
00049 typename RefHelper<T>::Ref RefHelper<T>::parentOrNull(const RefHelper<T>::Ref &ref) const { 
00050     if (backRefMap_.contains(ref.id())) {
00051         try {
00052             return backRefMap_[ref];
00053         } catch (edm::Exception &e) {
00054             if (e.categoryCode() == edm::errors::InvalidReference) {
00055                 return Ref();
00056             } else {
00057                 throw;
00058             }
00059         }
00060     } else {
00061         return Ref();
00062     }
00063 }
00064 
00065 template<typename T>
00066 typename RefHelper<T>::Ref RefHelper<T>::parentOrSelf(const RefHelper<T>::Ref &ref) const {
00067     Ref ret = parentOrNull(ref);
00068     return ret.isNonnull() ? ret : ref;
00069 }
00070 
00071 template<typename T>
00072 typename RefHelper<T>::Ref RefHelper<T>::ancestorOrSelf(const RefHelper<T>::Ref &ref) const {
00073     Ref ret = ref;
00074     do {
00075         Ref test = parentOrNull(ret);
00076         if (test.isNull()) return ret;
00077         ret = test;
00078     } while (true);
00079 }
00080 
00081 
00082 template<typename T>
00083 bool RefHelper<T>::isRoot(const RefHelper<T>::Ref &ref) const { 
00084     return parentOrNull(ref).isNull(); 
00085 }
00086 
00087 template<typename T>
00088 bool RefHelper<T>::isAncestorOf(const RefHelper<T>::Ref &old, const RefHelper<T>::Ref &young) const { 
00089     Ref test = young;
00090     do {
00091         if (test == old) return true;
00092         test = parentOrNull(test);
00093     } while (test.isNonnull());
00094     return false;
00095 }
00096 
00097 template<typename T>
00098 bool RefHelper<T>::sharedAncestor(const RefHelper<T>::Ref &ref1, const RefHelper<T>::Ref &ref2) const { 
00099     return ( ancestorOrSelf(ref1) == ancestorOrSelf(ref2) );
00100 }
00101 
00102 template<typename T>
00103 template<typename V, typename SomeRef>
00104 V RefHelper<T>::recursiveLookup(const SomeRef &ref, const edm::ValueMap<V> &map) const {
00105     Ref test(ref);
00106     do {
00107         if (map.contains(test.id())) {
00108             try {
00109                 return map[test];
00110             } catch (edm::Exception &e) {
00111                 if (e.categoryCode() != edm::errors::InvalidReference) {
00112                     throw;
00113                 }
00114             }
00115         } 
00116         test = parentOrNull(test);
00117     } while (test.isNonnull());
00118     throw edm::Exception(edm::errors::InvalidReference) <<
00119         "RefHelper: recursive Lookup failed: neither the specified ref nor any of its parents are in the map.\n";
00120 }
00121 
00122 template<typename T>
00123 template<typename V, typename SomeRef>
00124 V RefHelper<T>::ancestorLookup(const SomeRef &ref, const edm::ValueMap<V> &map) const {
00125     Ref tref(ref);
00126     return map[ancestorOrSelf(tref)];
00127 }
00128 
00129 } } // namespace
00130 #endif