Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-01-31 02:19:10

0001 #include "DataFormats/Provenance/interface/ProductDescription.h"
0002 
0003 #include "FWCore/Utilities/interface/EDMException.h"
0004 #include "FWCore/Utilities/interface/Exception.h"
0005 #include "FWCore/Utilities/interface/FriendlyName.h"
0006 #include "FWCore/Reflection/interface/FunctionWithDict.h"
0007 #include "FWCore/Reflection/interface/TypeWithDict.h"
0008 #include "FWCore/Utilities/interface/WrappedClassName.h"
0009 
0010 #include "TDictAttributeMap.h"
0011 
0012 #include <cassert>
0013 #include <ostream>
0014 #include <sstream>
0015 
0016 class TClass;
0017 
0018 namespace edm {
0019   BranchDescription::Transients::Transients()
0020       : branchName_(),
0021         wrappedName_(),
0022         wrappedType_(),
0023         unwrappedType_(),
0024         produced_(false),
0025         onDemand_(false),
0026         isTransform_(false),
0027         dropped_(false),
0028         transient_(false),
0029         availableOnlyAtEndTransition_(false),
0030         isMergeable_(false) {}
0031 
0032   void BranchDescription::Transients::reset() { *this = BranchDescription::Transients(); }
0033 
0034   BranchDescription::BranchDescription()
0035       : branchType_(InEvent),
0036         moduleLabel_(),
0037         processName_(),
0038         branchID_(),
0039         fullClassName_(),
0040         friendlyClassName_(),
0041         productInstanceName_(),
0042         branchAliases_(),
0043         aliasForBranchID_(),
0044         transient_() {
0045     // do not call init here! It will result in an exception throw.
0046   }
0047 
0048   BranchDescription::BranchDescription(BranchType const& branchType,
0049                                        std::string const& moduleLabel,
0050                                        std::string const& processName,
0051                                        std::string const& className,
0052                                        std::string const& friendlyClassName,
0053                                        std::string const& productInstanceName,
0054                                        TypeWithDict const& theTypeWithDict,
0055                                        bool produced,
0056                                        bool availableOnlyAtEndTransition,
0057                                        std::set<std::string> const& aliases)
0058       : branchType_(branchType),
0059         moduleLabel_(moduleLabel),
0060         processName_(processName),
0061         branchID_(),
0062         fullClassName_(className),
0063         friendlyClassName_(friendlyClassName),
0064         productInstanceName_(productInstanceName),
0065         branchAliases_(aliases),
0066         transient_() {
0067     setDropped(false);
0068     setProduced(produced);
0069     setOnDemand(false);
0070     transient_.availableOnlyAtEndTransition_ = availableOnlyAtEndTransition;
0071     setUnwrappedType(theTypeWithDict);
0072     init();
0073   }
0074 
0075   BranchDescription::BranchDescription(BranchDescription const& aliasForBranch,
0076                                        std::string const& moduleLabelAlias,
0077                                        std::string const& productInstanceAlias)
0078       : branchType_(aliasForBranch.branchType()),
0079         moduleLabel_(moduleLabelAlias),
0080         processName_(aliasForBranch.processName()),
0081         branchID_(),
0082         fullClassName_(aliasForBranch.className()),
0083         friendlyClassName_(aliasForBranch.friendlyClassName()),
0084         productInstanceName_(productInstanceAlias),
0085         branchAliases_(aliasForBranch.branchAliases()),
0086         aliasForBranchID_(aliasForBranch.branchID()),
0087         transient_() {
0088     setDropped(false);
0089     setProduced(aliasForBranch.produced());
0090     setOnDemand(false);  // will be re-set externally to the aliasForBranch.onDemand() after that one has been set
0091     transient_.availableOnlyAtEndTransition_ = aliasForBranch.availableOnlyAtEndTransition();
0092     setUnwrappedType(aliasForBranch.unwrappedType());
0093     init();
0094   }
0095 
0096   void BranchDescription::initBranchName() {
0097     if (!branchName().empty()) {
0098       return;  // already called
0099     }
0100     throwIfInvalid_();
0101 
0102     char const underscore('_');
0103     char const period('.');
0104 
0105     if (friendlyClassName_.find(underscore) != std::string::npos) {
0106       throw cms::Exception("IllegalCharacter")
0107           << "Class name '" << friendlyClassName()
0108           << "' contains an underscore ('_'), which is illegal in the name of a product.\n";
0109     }
0110 
0111     // Module labels of non-persistent products are allowed to contain
0112     // underscores. For module labels of persistent products, the module
0113     // label is checked for underscores in the function initFromDictionary
0114     // after we determine whether the product is persistent or not.
0115 
0116     if (productInstanceName_.find(underscore) != std::string::npos) {
0117       throw cms::Exception("IllegalCharacter")
0118           << "Product instance name '" << productInstanceName()
0119           << "' contains an underscore ('_'), which is illegal in a product instance name.\n";
0120     }
0121 
0122     if (processName_.find(underscore) != std::string::npos) {
0123       throw cms::Exception("IllegalCharacter")
0124           << "Process name '" << processName()
0125           << "' contains an underscore ('_'), which is illegal in a process name.\n";
0126     }
0127 
0128     std::string& brName = transient_.branchName_;
0129     brName.reserve(friendlyClassName().size() + moduleLabel().size() + productInstanceName().size() +
0130                    processName().size() + 4);
0131     brName += friendlyClassName();
0132     brName += underscore;
0133     brName += moduleLabel();
0134     brName += underscore;
0135     brName += productInstanceName();
0136     brName += underscore;
0137     brName += processName();
0138     brName += period;
0139 
0140     if (!branchID_.isValid()) {
0141       branchID_.setID(brName);
0142     }
0143   }
0144 
0145   void BranchDescription::initFromDictionary() {
0146     if (bool(wrappedType())) {
0147       return;  // already initialized;
0148     }
0149 
0150     throwIfInvalid_();
0151 
0152     try {
0153       setWrappedName(wrappedClassName(fullClassName()));
0154       // unwrapped type.
0155       setUnwrappedType(TypeWithDict::byName(fullClassName()));
0156       if (!bool(unwrappedType())) {
0157         setTransient(false);
0158         return;
0159       }
0160     } catch (edm::Exception& caughtException) {
0161       caughtException.addContext(std::string{"While initializing meta data for branch: "} + branchName());
0162       throw;
0163     }
0164 
0165     edm::TypeWithDict wrType(TypeWithDict::byName(wrappedName()));
0166     try {
0167       setWrappedType(wrType);
0168       if (!bool(wrappedType())) {
0169         return;
0170       }
0171     } catch (edm::Exception& caughtException) {
0172       caughtException.addContext(std::string{"While initializing meta data for branch: "} + branchName());
0173       throw;
0174     }
0175 
0176     setTransient(false);
0177     TDictAttributeMap* wp = wrappedType().getClass()->GetAttributeMap();
0178     if (wp && wp->HasKey("persistent") && !strcmp(wp->GetPropertyAsString("persistent"), "false")) {
0179       // Set transient if persistent == "false".
0180       setTransient(true);
0181       return;
0182     } else {
0183       // Module labels of persistent products cannot contain underscores,
0184       // but for non-persistent products it is allowed because path names
0185       // are used as module labels for path status products and there
0186       // are many path names that include underscores.
0187       char const underscore('_');
0188       if (moduleLabel_.find(underscore) != std::string::npos) {
0189         throw cms::Exception("IllegalCharacter")
0190             << "Module label '" << moduleLabel()
0191             << "' contains an underscore ('_'), which is illegal in a module label.\n";
0192       }
0193     }
0194   }
0195 
0196   void BranchDescription::merge(BranchDescription const& other) {
0197     branchAliases_.insert(other.branchAliases().begin(), other.branchAliases().end());
0198   }
0199 
0200   void BranchDescription::setSwitchAliasForBranch(BranchDescription const& aliasForBranch) {
0201     if (branchType_ != aliasForBranch.branchType()) {
0202       throw Exception(errors::LogicError) << "BranchDescription::setSwitchAliasForBranch: branchType (" << branchType_
0203                                           << ") differs from aliasForBranch (" << aliasForBranch.branchType()
0204                                           << ").\nPlease report this error to the FWCore developers";
0205     }
0206     if (produced() != aliasForBranch.produced()) {
0207       throw Exception(errors::LogicError) << "BranchDescription::setSwitchAliasForBranch: produced differs from "
0208                                              "aliasForBranch.\nPlease report this error to the FWCore developers";
0209     }
0210     if (unwrappedTypeID().typeInfo() != aliasForBranch.unwrappedType().typeInfo()) {
0211       throw Exception(errors::LogicError)
0212           << "BranchDescription::setSwitchAliasForBranch: unwrapped type info (" << unwrappedTypeID().name()
0213           << ") differs from aliasForBranch (" << aliasForBranch.unwrappedType().typeInfo().name()
0214           << ").\nPlease report this error to the FWCore developers";
0215     }
0216 
0217     branchAliases_ = aliasForBranch.branchAliases();
0218     transient_.switchAliasForBranchID_ = aliasForBranch.originalBranchID();
0219     transient_.availableOnlyAtEndTransition_ = aliasForBranch.availableOnlyAtEndTransition();
0220   }
0221 
0222   void BranchDescription::write(std::ostream& os) const {
0223     os << "Branch Type = " << branchType() << std::endl;
0224     os << "Process Name = " << processName() << std::endl;
0225     os << "ModuleLabel = " << moduleLabel() << std::endl;
0226     os << "Branch ID = " << branchID() << '\n';
0227     os << "Class Name = " << fullClassName() << '\n';
0228     os << "Friendly Class Name = " << friendlyClassName() << '\n';
0229     os << "Product Instance Name = " << productInstanceName() << std::endl;
0230   }
0231 
0232   void throwExceptionWithText(char const* txt) {
0233     Exception e(errors::LogicError);
0234     e << "Problem using an incomplete BranchDescription\n"
0235       << txt << "\nPlease report this error to the FWCore developers";
0236     throw e;
0237   }
0238 
0239   void BranchDescription::throwIfInvalid_() const {
0240     if (branchType_ >= NumBranchTypes)
0241       throwExceptionWithText("Illegal BranchType detected");
0242 
0243     if (moduleLabel_.empty())
0244       throwExceptionWithText("Module label is not allowed to be empty");
0245 
0246     if (processName_.empty())
0247       throwExceptionWithText("Process name is not allowed to be empty");
0248 
0249     if (fullClassName_.empty())
0250       throwExceptionWithText("Full class name is not allowed to be empty");
0251 
0252     if (friendlyClassName_.empty())
0253       throwExceptionWithText("Friendly class name is not allowed to be empty");
0254   }
0255 
0256   void BranchDescription::updateFriendlyClassName() {
0257     friendlyClassName_ = friendlyname::friendlyName(fullClassName());
0258     clearBranchName();
0259     initBranchName();
0260   }
0261 
0262   bool operator<(BranchDescription const& a, BranchDescription const& b) {
0263     if (a.processName() < b.processName())
0264       return true;
0265     if (b.processName() < a.processName())
0266       return false;
0267     if (a.fullClassName() < b.fullClassName())
0268       return true;
0269     if (b.fullClassName() < a.fullClassName())
0270       return false;
0271     if (a.friendlyClassName() < b.friendlyClassName())
0272       return true;
0273     if (b.friendlyClassName() < a.friendlyClassName())
0274       return false;
0275     if (a.productInstanceName() < b.productInstanceName())
0276       return true;
0277     if (b.productInstanceName() < a.productInstanceName())
0278       return false;
0279     if (a.moduleLabel() < b.moduleLabel())
0280       return true;
0281     if (b.moduleLabel() < a.moduleLabel())
0282       return false;
0283     if (a.branchType() < b.branchType())
0284       return true;
0285     if (b.branchType() < a.branchType())
0286       return false;
0287     if (a.branchID() < b.branchID())
0288       return true;
0289     if (b.branchID() < a.branchID())
0290       return false;
0291     if (a.branchAliases() < b.branchAliases())
0292       return true;
0293     if (b.branchAliases() < a.branchAliases())
0294       return false;
0295     if (a.present() < b.present())
0296       return true;
0297     if (b.present() < a.present())
0298       return false;
0299     return false;
0300   }
0301 
0302   bool combinable(BranchDescription const& a, BranchDescription const& b) {
0303     return (a.branchType() == b.branchType()) && (a.processName() == b.processName()) &&
0304            (a.fullClassName() == b.fullClassName()) && (a.friendlyClassName() == b.friendlyClassName()) &&
0305            (a.productInstanceName() == b.productInstanceName()) && (a.moduleLabel() == b.moduleLabel()) &&
0306            (a.branchID() == b.branchID());
0307   }
0308 
0309   bool operator==(BranchDescription const& a, BranchDescription const& b) {
0310     return combinable(a, b) && (a.dropped() == b.dropped()) && (a.branchAliases() == b.branchAliases());
0311   }
0312 
0313   std::string match(BranchDescription const& a, BranchDescription const& b, std::string const& fileName) {
0314     std::ostringstream differences;
0315     if (a.branchName() != b.branchName()) {
0316       differences << "Branch name '" << b.branchName() << "' does not match '" << a.branchName() << "'.\n";
0317       // Need not compare components of branch name individually.
0318       // (a.friendlyClassName() != b.friendlyClassName())
0319       // (a.moduleLabel() != b.moduleLabel())
0320       // (a.productInstanceName() != b.productInstanceName())
0321       // (a.processName() != b.processName())
0322     }
0323     if (a.branchType() != b.branchType()) {
0324       differences << "Branch '" << b.branchName() << "' is a(n) '" << b.branchType() << "' branch\n";
0325       differences << "    in file '" << fileName << "', but a(n) '" << a.branchType()
0326                   << "' branch in previous files.\n";
0327     }
0328     if (a.branchID() != b.branchID()) {
0329       differences << "Branch '" << b.branchName() << "' has a branch ID of '" << b.branchID() << "'\n";
0330       differences << "    in file '" << fileName << "', but '" << a.branchID() << "' in previous files.\n";
0331     }
0332     if (a.fullClassName() != b.fullClassName()) {
0333       differences << "Products on branch '" << b.branchName() << "' have type '" << b.fullClassName() << "'\n";
0334       differences << "    in file '" << fileName << "', but '" << a.fullClassName() << "' in previous files.\n";
0335     }
0336     if (!b.dropped() && a.dropped()) {
0337       differences << "Branch '" << a.branchName() << "' was dropped in the first input file but is present in '"
0338                   << fileName << "'.\n";
0339     }
0340     return differences.str();
0341   }
0342 }  // namespace edm