CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC4_patch1/src/FWCore/Utilities/src/DictionaryTools.cc

Go to the documentation of this file.
00001 #include "FWCore/Utilities/interface/DictionaryTools.h"
00002 #include "FWCore/Utilities/interface/Algorithms.h"
00003 #include "FWCore/Utilities/interface/EDMException.h"
00004 #include "FWCore/Utilities/interface/BaseWithDict.h"
00005 #include "FWCore/Utilities/interface/MemberWithDict.h"
00006 #include "FWCore/Utilities/interface/TypeWithDict.h"
00007 #include "FWCore/Utilities/interface/TypeWithDict.h"
00008 
00009 #include "Api.h" // for G__ClassInfo
00010 
00011 #include "TROOT.h"
00012 
00013 #include "boost/algorithm/string.hpp"
00014 #include "boost/thread/tss.hpp"
00015 
00016 #include <algorithm>
00017 #include <sstream>
00018 
00019 namespace edm {
00020 
00021   std::string const& dictionaryPlugInPrefix() {
00022     static std::string const prefix("LCGReflex/");
00023     return prefix;
00024   }
00025 
00026   static StringSet foundTypes_;
00027   static StringSet missingTypes_;
00028 
00029   bool
00030   find_nested_type_named(std::string const& nested_type,
00031                          TypeWithDict const& typeToSearch,
00032                          TypeWithDict& found_type) {
00033     // Look for a sub-type named 'nested_type'
00034     TypeWithDict foundType = typeToSearch.nestedType(nested_type);
00035     if(bool(foundType)) {
00036       found_type = foundType.finalType();
00037       return true;
00038     }
00039     return false;
00040   }
00041 
00042   bool
00043   is_RefVector(TypeWithDict const& possibleRefVector,
00044                TypeWithDict& value_type) {
00045 
00046     static TypeTemplateWithDict ref_vector_template_id(TypeTemplateWithDict::byName("edm::RefVector", 3));
00047     static std::string member_type("member_type");
00048     TypeTemplateWithDict primary_template_id(possibleRefVector);
00049     if(primary_template_id == ref_vector_template_id) {
00050       return find_nested_type_named(member_type, possibleRefVector, value_type);
00051     }
00052     return false;
00053   }
00054 
00055   bool
00056   is_PtrVector(TypeWithDict const& possibleRefVector,
00057                TypeWithDict& value_type) {
00058 
00059     static TypeTemplateWithDict ref_vector_template_id(TypeTemplateWithDict::byName("edm::PtrVector", 1));
00060     static std::string member_type("member_type");
00061     static std::string val_type("value_type");
00062     TypeTemplateWithDict primary_template_id(possibleRefVector);
00063     if(primary_template_id == ref_vector_template_id) {
00064       TypeWithDict ptrType;
00065       if(find_nested_type_named(val_type, possibleRefVector, ptrType)) {
00066         return find_nested_type_named(val_type, ptrType, value_type);
00067       }
00068     }
00069     return false;
00070   }
00071 
00072   bool
00073   is_RefToBaseVector(TypeWithDict const& possibleRefVector,
00074                      TypeWithDict& value_type) {
00075 
00076     static TypeTemplateWithDict ref_vector_template_id(TypeTemplateWithDict::byName("edm::RefToBaseVector", 1));
00077     static std::string member_type("member_type");
00078     TypeTemplateWithDict primary_template_id(possibleRefVector);
00079     if(primary_template_id == ref_vector_template_id) {
00080       return find_nested_type_named(member_type, possibleRefVector, value_type);
00081     }
00082     return false;
00083   }
00084 
00085   namespace {
00086 
00087     int const oneParamArraySize = 6;
00088     std::string const oneParam[oneParamArraySize] = {
00089       "vector",
00090       "basic_string",
00091       "set",
00092       "list",
00093       "deque",
00094       "multiset"
00095     };
00096     int const twoParamArraySize = 3;
00097     std::string const twoParam[twoParamArraySize] = {
00098       "map",
00099       "pair",
00100       "multimap"
00101     };
00102 
00103 
00104     bool
00105     hasCintDictionary(std::string const& name) {
00106       std::auto_ptr<G__ClassInfo> ci(new G__ClassInfo(name.c_str()));
00107         return(ci.get() && ci->IsLoaded());
00108     }
00109 
00110     // Checks if there is a dictionary for the Type t.
00111     // If noComponents is false, checks members and base classes recursively.
00112     // If noComponents is true, checks Type t only.
00113     void
00114     checkType(TypeWithDict t, bool noComponents = false) {
00115 
00116       // ToType strips const, volatile, array, pointer, reference, etc.,
00117       // and also translates typedefs.
00118       // To be safe, we do this recursively until we either get a null type
00119       // or the same type.
00120       TypeWithDict null;
00121       for(TypeWithDict x(t.toType()); x != null && x != t; t = x, x = t.toType()) {}
00122 
00123       std::string name(t.name());
00124       boost::trim(name);
00125 
00126       if(foundTypes().end() != foundTypes().find(name) || missingTypes().end() != missingTypes().find(name)) {
00127         // Already been processed. Prevents infinite loop.
00128         return;
00129       }
00130 
00131       if(name.empty() || t.isFundamental() || t.isEnum()) {
00132         foundTypes().insert(name);
00133         return;
00134       }
00135 
00136       if(!bool(t)) {
00137         if(hasCintDictionary(name)) {
00138           foundTypes().insert(name);
00139         } else {
00140           missingTypes().insert(name);
00141         }
00142         return;
00143       }
00144 
00145       foundTypes().insert(name);
00146       if(noComponents) return;
00147 
00148       if(name.find("std::") == 0) {
00149         if(t.isTemplateInstance()) {
00150           std::string::size_type n = name.find('<');
00151           int cnt = 0;
00152           if(std::find(oneParam, oneParam + oneParamArraySize, name.substr(5, n - 5)) != oneParam + oneParamArraySize) {
00153             cnt = 1;
00154           } else if(std::find(twoParam, twoParam + twoParamArraySize, name.substr(5, n - 5)) != twoParam + twoParamArraySize) {
00155             cnt = 2;
00156           }
00157           for(int i = 0; i < cnt; ++i) {
00158             checkType(t.templateArgumentAt(i));
00159           }
00160         }
00161       } else {
00162         TypeDataMembers members(t);
00163         for(auto const& member : members) {
00164           MemberWithDict m(member);
00165           if(!m.isTransient() && !m.isStatic()) {
00166             checkType(m.typeOf());
00167           }
00168         }
00169         TypeBases bases(t);
00170         for(auto const& base : bases) {
00171           BaseWithDict b(base);
00172           checkType(b.toType());
00173         }
00174       }
00175     }
00176   } // end unnamed namespace
00177 
00178   StringSet& missingTypes() {
00179     return missingTypes_;
00180   }
00181 
00182   StringSet& foundTypes() {
00183     // The only purpose of this cache is to stop infinite recursion.
00184     // ROOT maintains its own internal cache.
00185     return foundTypes_;
00186   }
00187 
00188   void checkDictionaries(std::string const& name, bool noComponents) {
00189     TypeWithDict null;
00190     TypeWithDict t(TypeWithDict::byName(name));
00191     if(t == null) {
00192       missingTypes().insert(name);
00193       return;
00194     }
00195     checkType(t, noComponents);
00196   }
00197 
00198   void throwMissingDictionariesException() {
00199     if(!missingTypes().empty()) {
00200       std::ostringstream ostr;
00201       for (StringSet::const_iterator it = missingTypes().begin(), itEnd = missingTypes().end();
00202            it != itEnd; ++it) {
00203         ostr << *it << "\n\n";
00204       }
00205       throw Exception(errors::DictionaryNotFound)
00206         << "No REFLEX data dictionary found for the following classes:\n\n"
00207         << ostr.str()
00208         << "Most likely each dictionary was never generated,\n"
00209         << "but it may be that it was generated in the wrong package.\n"
00210         << "Please add (or move) the specification\n"
00211         << "<class name=\"whatever\"/>\n"
00212         << "to the appropriate classes_def.xml file.\n"
00213         << "If the class is a template instance, you may need\n"
00214         << "to define a dummy variable of this type in classes.h.\n"
00215         << "Also, if this class has any transient members,\n"
00216         << "you need to specify them in classes_def.xml.";
00217     }
00218   }
00219 
00220   void loadMissingDictionaries() {
00221     while (!missingTypes().empty()) {
00222       StringSet missing(missingTypes());
00223       for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end();
00224          it != itEnd; ++it) {
00225         try {
00226           gROOT->GetClass(it->c_str(), kTRUE);
00227         }
00228         // We don't want to fail if we can't load a plug-in.
00229         catch(...) {}
00230       }
00231       missingTypes().clear();
00232       for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end();
00233          it != itEnd; ++it) {
00234         checkDictionaries(*it);
00235       }
00236       if (missingTypes() == missing) {
00237         break;
00238       }
00239     }
00240     if (missingTypes().empty()) {
00241       return;
00242     }
00243     throwMissingDictionariesException();
00244   }
00245 
00246   void public_base_classes(TypeWithDict const& typeID,
00247                            std::vector<TypeWithDict>& baseTypes) {
00248 
00249     TypeWithDict type(typeID.typeInfo());
00250     if(type.isClass() || type.isStruct()) {
00251 
00252       TypeBases bases(type);
00253       for(auto const& basex : bases) {
00254         BaseWithDict base(basex);
00255         if(base.isPublic()) {
00256 
00257           TypeWithDict baseRflxType = base.toType();
00258           if(bool(baseRflxType)) {
00259             TypeWithDict baseType(baseRflxType.finalType().typeInfo()); 
00260 
00261             // Check to make sure this base appears only once in the
00262             // inheritance heirarchy.
00263             if(!search_all(baseTypes, baseType)) {
00264               // Save the type and recursive look for its base types
00265               baseTypes.push_back(baseType);
00266               public_base_classes(baseType, baseTypes);
00267             }
00268             // For now just ignore it if the class appears twice,
00269             // After some more testing we may decide to uncomment the following
00270             // exception.
00271             /*
00272             else {
00273               throw Exception(errors::UnimplementedFeature)
00274                 << "DataFormats/Common/src/DictionaryTools.cc in function public_base_classes.\n"
00275                 << "Encountered class that has a public base class that appears\n"
00276                 << "multiple times in its inheritance heirarchy.\n"
00277                 << "Please contact the EDM Framework group with details about\n"
00278                 << "this exception. It was our hope that this complicated situation\n"
00279                 << "would not occur. There are three possible solutions. 1. Change\n"
00280                 << "the class design so the public base class does not appear multiple\n"
00281                 << "times in the inheritance heirarchy. In many cases, this is a\n"
00282                 << "sign of bad design. 2. Modify the code that supports Views to\n"
00283                 << "ignore these base classes, but not supply support for creating a\n"
00284                 << "View of this base class. 3. Improve the View infrastructure to\n"
00285                 << "deal with this case. Class name of base class: " << baseType.Name() << "\n\n";
00286             }
00287             */
00288           }
00289         }
00290       }
00291     }
00292   }
00293 }