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
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 } }
00130 #endif