CMS 3D CMS Logo

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