CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_4_5_patch3/src/DataFormats/Provenance/src/BranchDescription.cc

Go to the documentation of this file.
00001 #include "DataFormats/Provenance/interface/BranchDescription.h"
00002 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00003 #include "FWCore/Utilities/interface/Exception.h"
00004 #include "FWCore/Utilities/interface/EDMException.h"
00005 #include "FWCore/Utilities/interface/FriendlyName.h"
00006 #include "FWCore/Utilities/interface/WrappedClassName.h"
00007 
00008 #include "Reflex/Member.h"
00009 
00010 #include <ostream>
00011 #include <sstream>
00012 #include <stdlib.h>
00013 
00014 class TClass;
00015 /*----------------------------------------------------------------------
00016 
00017 
00018 ----------------------------------------------------------------------*/
00019 
00020 namespace edm {
00021   BranchDescription::Transients::Transients() :
00022     parameterSetID_(),
00023     branchName_(),
00024     wrappedName_(),
00025     produced_(false),
00026     onDemand_(false),
00027     dropped_(false),
00028     parameterSetIDs_(),
00029     moduleNames_(),
00030     transient_(false),
00031     type_(),
00032     typeID_(),
00033     wrapperInterfaceBase_(0),
00034     splitLevel_(),
00035     basketSize_() {
00036    }
00037 
00038   BranchDescription::BranchDescription() :
00039     branchType_(InEvent),
00040     moduleLabel_(),
00041     processName_(),
00042     branchID_(),
00043     productID_(),
00044     fullClassName_(),
00045     friendlyClassName_(),
00046     productInstanceName_(),
00047     branchAliases_(),
00048     transients_() {
00049     // do not call init here! It will result in an exception throw.
00050   }
00051 
00052   BranchDescription::BranchDescription(
00053                         BranchType const& branchType,
00054                         std::string const& mdLabel,
00055                         std::string const& procName,
00056                         std::string const& name,
00057                         std::string const& fName,
00058                         std::string const& pin,
00059                         ModuleDescription const& modDesc,
00060                         TypeID const& theTypeID,
00061                         std::set<std::string> const& aliases) :
00062       branchType_(branchType),
00063       moduleLabel_(mdLabel),
00064       processName_(procName),
00065       branchID_(),
00066       productID_(),
00067       fullClassName_(name),
00068       friendlyClassName_(fName),
00069       productInstanceName_(pin),
00070       branchAliases_(aliases),
00071       transients_() {
00072     dropped() = false;
00073     produced() = true;
00074     onDemand() = false;
00075     typeID() = theTypeID;
00076     transients_.get().parameterSetID_ = modDesc.parameterSetID();
00077     transients_.get().moduleName_ = modDesc.moduleName();
00078     init();
00079   }
00080 
00081   void
00082   BranchDescription::initBranchName() const {
00083     if(!branchName().empty()) {
00084       return;  // already called
00085     }
00086     throwIfInvalid_();
00087 
00088     char const underscore('_');
00089     char const period('.');
00090 
00091     if(friendlyClassName_.find(underscore) != std::string::npos) {
00092       throw cms::Exception("IllegalCharacter") << "Class name '" << friendlyClassName()
00093       << "' contains an underscore ('_'), which is illegal in the name of a product.\n";
00094     }
00095 
00096     if(moduleLabel_.find(underscore) != std::string::npos) {
00097       throw cms::Exception("IllegalCharacter") << "Module label '" << moduleLabel()
00098       << "' contains an underscore ('_'), which is illegal in a module label.\n";
00099     }
00100 
00101     if(productInstanceName_.find(underscore) != std::string::npos) {
00102       throw cms::Exception("IllegalCharacter") << "Product instance name '" << productInstanceName()
00103       << "' contains an underscore ('_'), which is illegal in a product instance name.\n";
00104     }
00105 
00106     if(processName_.find(underscore) != std::string::npos) {
00107       throw cms::Exception("IllegalCharacter") << "Process name '" << processName()
00108       << "' contains an underscore ('_'), which is illegal in a process name.\n";
00109     }
00110 
00111     branchName().reserve(friendlyClassName().size() +
00112                          moduleLabel().size() +
00113                          productInstanceName().size() +
00114                          processName().size() + 4);
00115     branchName() += friendlyClassName();
00116     branchName() += underscore;
00117     branchName() += moduleLabel();
00118     branchName() += underscore;
00119     branchName() += productInstanceName();
00120     branchName() += underscore;
00121     branchName() += processName();
00122     branchName() += period;
00123 
00124     if(!branchID_.isValid()) {
00125       branchID_.setID(branchName());
00126     }
00127   }
00128 
00129   void
00130   BranchDescription::initFromDictionary() const {
00131     Reflex::Type null;
00132 
00133     if(type() != null) {
00134       return;  // already initialized;
00135     }
00136 
00137     throwIfInvalid_();
00138 
00139     wrappedName() = wrappedClassName(fullClassName());
00140 
00141     Reflex::Type t = Reflex::Type::ByName(fullClassName());
00142     if(t == null) {
00143       splitLevel() = invalidSplitLevel;
00144       basketSize() = invalidBasketSize;
00145       transient() = false;
00146       return;
00147     }
00148     typeID() = TypeID(t.TypeInfo()); // unwrapped type.
00149     type() = Reflex::Type::ByName(wrappedName());
00150     if(type() == null) {
00151       splitLevel() = invalidSplitLevel;
00152       basketSize() = invalidBasketSize;
00153       return;
00154     }
00155     Reflex::PropertyList wp = type().Properties();
00156     transient() = (wp.HasProperty("persistent") ? wp.PropertyAsString("persistent") == std::string("false") : false);
00157     if(transient()) {
00158       splitLevel() = invalidSplitLevel;
00159       basketSize() = invalidBasketSize;
00160       return;
00161     }
00162     if(wp.HasProperty("splitLevel")) {
00163       splitLevel() = strtol(wp.PropertyAsString("splitLevel").c_str(), 0, 0);
00164       if(splitLevel() < 0) {
00165         throw cms::Exception("IllegalSplitLevel") << "' An illegal ROOT split level of " <<
00166         splitLevel() << " is specified for class " << wrappedName() << ".'\n";
00167       }
00168       ++splitLevel(); //Compensate for wrapper
00169     } else {
00170       splitLevel() = invalidSplitLevel;
00171     }
00172     if(wp.HasProperty("basketSize")) {
00173       basketSize() = strtol(wp.PropertyAsString("basketSize").c_str(), 0, 0);
00174       if(basketSize() <= 0) {
00175         throw cms::Exception("IllegalBasketSize") << "' An illegal ROOT basket size of " <<
00176         basketSize() << " is specified for class " << wrappedName() << "'.\n";
00177       }
00178     } else {
00179       basketSize() = invalidBasketSize;
00180     }
00181   }
00182 
00183   ParameterSetID const&
00184     BranchDescription::psetID() const {
00185     assert(!parameterSetIDs().empty());
00186     if(parameterSetIDs().size() != 1) {
00187       throw cms::Exception("Ambiguous")
00188         << "Your application requires all events on Branch '" << branchName()
00189         << "'\n to have the same provenance. This file has events with mixed provenance\n"
00190         << "on this branch.  Use a different input file.\n";
00191     }
00192     return parameterSetIDs().begin()->second;
00193   }
00194 
00195   void
00196   BranchDescription::merge(BranchDescription const& other) {
00197     parameterSetIDs().insert(other.parameterSetIDs().begin(), other.parameterSetIDs().end());
00198     moduleNames().insert(other.moduleNames().begin(), other.moduleNames().end());
00199     branchAliases_.insert(other.branchAliases().begin(), other.branchAliases().end());
00200     if(splitLevel() == invalidSplitLevel) splitLevel() = other.splitLevel();
00201     if(basketSize() == invalidBasketSize) basketSize() = other.basketSize();
00202   }
00203 
00204   void
00205   BranchDescription::write(std::ostream& os) const {
00206     os << "Branch Type = " << branchType() << std::endl;
00207     os << "Process Name = " << processName() << std::endl;
00208     os << "ModuleLabel = " << moduleLabel() << std::endl;
00209     os << "Branch ID = " << branchID() << '\n';
00210     os << "Class Name = " << fullClassName() << '\n';
00211     os << "Friendly Class Name = " << friendlyClassName() << '\n';
00212     os << "Product Instance Name = " << productInstanceName() << std::endl;
00213   }
00214 
00215   void throwExceptionWithText(char const* txt) {
00216     Exception e(errors::LogicError);
00217     e << "Problem using an incomplete BranchDescription\n"
00218       << txt
00219       << "\nPlease report this error to the FWCore developers";
00220     throw e;
00221   }
00222 
00223   void
00224   BranchDescription::throwIfInvalid_() const {
00225     if(branchType_ >= NumBranchTypes)
00226       throwExceptionWithText("Illegal BranchType detected");
00227 
00228     if(moduleLabel_.empty())
00229       throwExceptionWithText("Module label is not allowed to be empty");
00230 
00231     if(processName_.empty())
00232       throwExceptionWithText("Process name is not allowed to be empty");
00233 
00234     if(fullClassName_.empty())
00235       throwExceptionWithText("Full class name is not allowed to be empty");
00236 
00237     if(friendlyClassName_.empty())
00238       throwExceptionWithText("Friendly class name is not allowed to be empty");
00239 
00240     if(produced() && !parameterSetID().isValid())
00241       throwExceptionWithText("Invalid ParameterSetID detected");
00242   }
00243 
00244   void
00245   BranchDescription::updateFriendlyClassName() {
00246     friendlyClassName_ = friendlyname::friendlyName(fullClassName());
00247     branchName().clear();
00248     initBranchName();
00249   }
00250 
00251   bool
00252   operator<(BranchDescription const& a, BranchDescription const& b) {
00253     if(a.processName() < b.processName()) return true;
00254     if(b.processName() < a.processName()) return false;
00255     if(a.fullClassName() < b.fullClassName()) return true;
00256     if(b.fullClassName() < a.fullClassName()) return false;
00257     if(a.friendlyClassName() < b.friendlyClassName()) return true;
00258     if(b.friendlyClassName() < a.friendlyClassName()) return false;
00259     if(a.productInstanceName() < b.productInstanceName()) return true;
00260     if(b.productInstanceName() < a.productInstanceName()) return false;
00261     if(a.moduleLabel() < b.moduleLabel()) return true;
00262     if(b.moduleLabel() < a.moduleLabel()) return false;
00263     if(a.branchType() < b.branchType()) return true;
00264     if(b.branchType() < a.branchType()) return false;
00265     if(a.branchID() < b.branchID()) return true;
00266     if(b.branchID() < a.branchID()) return false;
00267     if(a.parameterSetIDs() < b.parameterSetIDs()) return true;
00268     if(b.parameterSetIDs() < a.parameterSetIDs()) return false;
00269     if(a.moduleNames() < b.moduleNames()) return true;
00270     if(b.moduleNames() < a.moduleNames()) return false;
00271     if(a.branchAliases() < b.branchAliases()) return true;
00272     if(b.branchAliases() < a.branchAliases()) return false;
00273     if(a.present() < b.present()) return true;
00274     if(b.present() < a.present()) return false;
00275     return false;
00276   }
00277 
00278   bool
00279   combinable(BranchDescription const& a, BranchDescription const& b) {
00280     return
00281     (a.branchType() == b.branchType()) &&
00282     (a.processName() == b.processName()) &&
00283     (a.fullClassName() == b.fullClassName()) &&
00284     (a.friendlyClassName() == b.friendlyClassName()) &&
00285     (a.productInstanceName() == b.productInstanceName()) &&
00286     (a.moduleLabel() == b.moduleLabel()) &&
00287     (a.branchID() == b.branchID());
00288   }
00289 
00290   bool
00291   operator==(BranchDescription const& a, BranchDescription const& b) {
00292     return combinable(a, b) &&
00293        (a.dropped() == b.dropped()) &&
00294        (a.moduleNames() == b.moduleNames()) &&
00295        (a.parameterSetIDs() == b.parameterSetIDs()) &&
00296        (a.branchAliases() == b.branchAliases());
00297   }
00298 
00299   std::string
00300   match(BranchDescription const& a, BranchDescription const& b,
00301         std::string const& fileName,
00302         BranchDescription::MatchMode m) {
00303     std::ostringstream differences;
00304     if(a.branchName() != b.branchName()) {
00305       differences << "Branch name '" << b.branchName() << "' does not match '" << a.branchName() << "'.\n";
00306       // Need not compare components of branch name individually.
00307       // (a.friendlyClassName() != b.friendlyClassName())
00308       // (a.moduleLabel() != b.moduleLabel())
00309       // (a.productInstanceName() != b.productInstanceName())
00310       // (a.processName() != b.processName())
00311     }
00312     if(a.branchType() != b.branchType()) {
00313       differences << "Branch '" << b.branchName() << "' is a(n) '" << b.branchType() << "' branch\n";
00314       differences << "    in file '" << fileName << "', but a(n) '" << a.branchType() << "' branch in previous files.\n";
00315     }
00316     if(a.branchID() != b.branchID()) {
00317       differences << "Branch '" << b.branchName() << "' has a branch ID of '" << b.branchID() << "'\n";
00318       differences << "    in file '" << fileName << "', but '" << a.branchID() << "' in previous files.\n";
00319     }
00320     if(a.fullClassName() != b.fullClassName()) {
00321       differences << "Products on branch '" << b.branchName() << "' have type '" << b.fullClassName() << "'\n";
00322       differences << "    in file '" << fileName << "', but '" << a.fullClassName() << "' in previous files.\n";
00323     }
00324     if(!b.dropped() && a.dropped()) {
00325       differences << "Branch '" << a.branchName() << "' was dropped in the first input file but is present in '" << fileName << "'.\n";
00326     }
00327     if(m == BranchDescription::Strict) {
00328         if(b.parameterSetIDs().size() > 1) {
00329           differences << "Branch '" << b.branchName() << "' uses more than one parameter set in file '" << fileName << "'.\n";
00330         } else if(a.parameterSetIDs().size() > 1) {
00331           differences << "Branch '" << a.branchName() << "' uses more than one parameter set in previous files.\n";
00332         } else if(a.parameterSetIDs() != b.parameterSetIDs()) {
00333           differences << "Branch '" << b.branchName() << "' uses different parameter sets in file '" << fileName << "'.\n";
00334           differences << "    than in previous files.\n";
00335         }
00336     }
00337     return differences.str();
00338   }
00339 
00340   WrapperInterfaceBase const*
00341   BranchDescription::getInterface() const {
00342     if(wrapperInterfaceBase() == 0) {
00343       // This could be done in init(), but we only want to do it on demand, for performance reasons.
00344       Reflex::Type type = Reflex::Type::ByName(wrappedName());
00345       Reflex::Member getTheInterface = type.FunctionMemberByName(std::string("getInterface"));
00346       getTheInterface.Invoke(wrapperInterfaceBase());
00347       assert(wrapperInterfaceBase() != 0);
00348     }
00349     return wrapperInterfaceBase();
00350   }
00351 }