CMS 3D CMS Logo

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

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