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
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);
0091 transient_.availableOnlyAtEndTransition_ = aliasForBranch.availableOnlyAtEndTransition();
0092 setUnwrappedType(aliasForBranch.unwrappedType());
0093 init();
0094 }
0095
0096 void BranchDescription::initBranchName() {
0097 if (!branchName().empty()) {
0098 return;
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
0112
0113
0114
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;
0148 }
0149
0150 throwIfInvalid_();
0151
0152 try {
0153 setWrappedName(wrappedClassName(fullClassName()));
0154
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
0180 setTransient(true);
0181 return;
0182 } else {
0183
0184
0185
0186
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
0318
0319
0320
0321
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 }