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"
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
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
00111
00112
00113 void
00114 checkType(TypeWithDict t, bool noComponents = false) {
00115
00116
00117
00118
00119
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
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 }
00177
00178 StringSet& missingTypes() {
00179 return missingTypes_;
00180 }
00181
00182 StringSet& foundTypes() {
00183
00184
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
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
00262
00263 if(!search_all(baseTypes, baseType)) {
00264
00265 baseTypes.push_back(baseType);
00266 public_base_classes(baseType, baseTypes);
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 }
00292 }
00293 }