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
00008 #include "Api.h"
00009
00010 #include "TROOT.h"
00011
00012 #include "boost/algorithm/string.hpp"
00013 #include "boost/thread/tss.hpp"
00014
00015 #include <algorithm>
00016 #include <sstream>
00017
00018 namespace edm {
00019
00020 std::string const& dictionaryPlugInPrefix() {
00021 static std::string const prefix("LCGReflex/");
00022 return prefix;
00023 }
00024
00025 static StringSet foundTypes_;
00026 static StringSet missingTypes_;
00027
00028 bool
00029 find_nested_type_named(std::string const& nested_type,
00030 TypeWithDict const& typeToSearch,
00031 TypeWithDict& found_type) {
00032
00033 TypeWithDict foundType = typeToSearch.nestedType(nested_type);
00034 if(bool(foundType)) {
00035 found_type = foundType;
00036 return true;
00037 }
00038 return false;
00039 }
00040
00041 bool
00042 is_RefVector(TypeWithDict const& possibleRefVector,
00043 TypeWithDict& value_type) {
00044
00045 static std::string const template_name("edm::RefVector");
00046 static std::string const member_type("member_type");
00047 if(template_name == possibleRefVector.templateName()) {
00048 return find_nested_type_named(member_type, possibleRefVector, value_type);
00049 }
00050 return false;
00051 }
00052
00053 bool
00054 is_PtrVector(TypeWithDict const& possibleRefVector,
00055 TypeWithDict& value_type) {
00056
00057 static std::string const template_name("edm::PtrVector");
00058 static std::string const member_type("member_type");
00059 static std::string const val_type("value_type");
00060 if(template_name == possibleRefVector.templateName()) {
00061 TypeWithDict ptrType;
00062 if(find_nested_type_named(val_type, possibleRefVector, ptrType)) {
00063 return find_nested_type_named(val_type, ptrType, value_type);
00064 }
00065 }
00066 return false;
00067 }
00068
00069 bool
00070 is_RefToBaseVector(TypeWithDict const& possibleRefVector,
00071 TypeWithDict& value_type) {
00072
00073 static std::string const template_name("edm::RefToBaseVector");
00074 static std::string const member_type("member_type");
00075 if(template_name == possibleRefVector.templateName()) {
00076 return find_nested_type_named(member_type, possibleRefVector, value_type);
00077 }
00078 return false;
00079 }
00080
00081 namespace {
00082
00083 int const oneParamArraySize = 6;
00084 std::string const oneParam[oneParamArraySize] = {
00085 "vector",
00086 "basic_string",
00087 "set",
00088 "list",
00089 "deque",
00090 "multiset"
00091 };
00092 int const twoParamArraySize = 3;
00093 std::string const twoParam[twoParamArraySize] = {
00094 "map",
00095 "pair",
00096 "multimap"
00097 };
00098
00099
00100 bool
00101 hasCintDictionary(std::string const& name) {
00102 std::auto_ptr<G__ClassInfo> ci(new G__ClassInfo(name.c_str()));
00103 return(ci.get() && ci->IsLoaded());
00104 }
00105
00106
00107
00108
00109 void
00110 checkType(TypeWithDict t, bool noComponents = false) {
00111
00112
00113
00114
00115 for(TypeWithDict x(t.toType()); x != t && x.typeInfo() != typeid(void); t = x, x = t.toType()) {}
00116
00117 std::string name(t.name());
00118 boost::trim(name);
00119
00120 if(foundTypes().end() != foundTypes().find(name) || missingTypes().end() != missingTypes().find(name)) {
00121
00122 return;
00123 }
00124
00125 if(name.empty() || t.isFundamental() || t.isEnum() || t.typeInfo() == typeid(void)) {
00126 foundTypes().insert(name);
00127 return;
00128 }
00129
00130 if(!bool(t)) {
00131 if(hasCintDictionary(name)) {
00132 foundTypes().insert(name);
00133 } else {
00134 missingTypes().insert(name);
00135 }
00136 return;
00137 }
00138
00139 foundTypes().insert(name);
00140 if(noComponents) return;
00141
00142 if(name.find("std::") == 0) {
00143 if(t.isTemplateInstance()) {
00144 std::string::size_type n = name.find('<');
00145 int cnt = 0;
00146 if(std::find(oneParam, oneParam + oneParamArraySize, name.substr(5, n - 5)) != oneParam + oneParamArraySize) {
00147 cnt = 1;
00148 } else if(std::find(twoParam, twoParam + twoParamArraySize, name.substr(5, n - 5)) != twoParam + twoParamArraySize) {
00149 cnt = 2;
00150 }
00151 for(int i = 0; i < cnt; ++i) {
00152 checkType(t.templateArgumentAt(i));
00153 }
00154 }
00155 } else {
00156 TypeDataMembers members(t);
00157 for(auto const& member : members) {
00158 MemberWithDict m(member);
00159 if(!m.isTransient() && !m.isStatic()) {
00160 checkType(m.typeOf());
00161 }
00162 }
00163 TypeBases bases(t);
00164 for(auto const& base : bases) {
00165 BaseWithDict b(base);
00166 checkType(b.typeOf());
00167 }
00168 }
00169 }
00170 }
00171
00172 StringSet& missingTypes() {
00173 return missingTypes_;
00174 }
00175
00176 StringSet& foundTypes() {
00177
00178
00179 return foundTypes_;
00180 }
00181
00182 void checkDictionaries(std::string const& name, bool noComponents) {
00183 TypeWithDict null;
00184 TypeWithDict t(TypeWithDict::byName(name));
00185 if(t == null) {
00186 if(name == std::string("void")) {
00187 foundTypes().insert(name);
00188 } else {
00189 missingTypes().insert(name);
00190 }
00191 return;
00192 }
00193 checkType(t, noComponents);
00194 }
00195
00196 void throwMissingDictionariesException() {
00197 if(!missingTypes().empty()) {
00198 std::ostringstream ostr;
00199 for (StringSet::const_iterator it = missingTypes().begin(), itEnd = missingTypes().end();
00200 it != itEnd; ++it) {
00201 ostr << *it << "\n\n";
00202 }
00203 throw Exception(errors::DictionaryNotFound)
00204 << "No REFLEX data dictionary found for the following classes:\n\n"
00205 << ostr.str()
00206 << "Most likely each dictionary was never generated,\n"
00207 << "but it may be that it was generated in the wrong package.\n"
00208 << "Please add (or move) the specification\n"
00209 << "<class name=\"whatever\"/>\n"
00210 << "to the appropriate classes_def.xml file.\n"
00211 << "If the class is a template instance, you may need\n"
00212 << "to define a dummy variable of this type in classes.h.\n"
00213 << "Also, if this class has any transient members,\n"
00214 << "you need to specify them in classes_def.xml.";
00215 }
00216 }
00217
00218 void loadMissingDictionaries() {
00219 while (!missingTypes().empty()) {
00220 StringSet missing(missingTypes());
00221 for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end();
00222 it != itEnd; ++it) {
00223 try {
00224 gROOT->GetClass(it->c_str(), kTRUE);
00225 }
00226
00227 catch(...) {}
00228 }
00229 missingTypes().clear();
00230 for (StringSet::const_iterator it = missing.begin(), itEnd = missing.end();
00231 it != itEnd; ++it) {
00232 checkDictionaries(*it);
00233 }
00234 if (missingTypes() == missing) {
00235 break;
00236 }
00237 }
00238 if (missingTypes().empty()) {
00239 return;
00240 }
00241 throwMissingDictionariesException();
00242 }
00243
00244 void public_base_classes(TypeWithDict const& typeID,
00245 std::vector<TypeWithDict>& baseTypes) {
00246
00247 TypeWithDict type(typeID.typeInfo());
00248 if(type.isClass()) {
00249
00250 TypeBases bases(type);
00251 for(auto const& basex : bases) {
00252 BaseWithDict base(basex);
00253 if(base.isPublic()) {
00254
00255 TypeWithDict baseRflxType = base.typeOf();
00256 if(bool(baseRflxType)) {
00257 TypeWithDict baseType(baseRflxType.typeInfo());
00258
00259
00260
00261 if(!search_all(baseTypes, baseType)) {
00262
00263 baseTypes.push_back(baseType);
00264 public_base_classes(baseType, baseTypes);
00265 }
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 }
00287 }
00288 }
00289 }
00290 }
00291 }