File indexing completed on 2025-03-13 02:31:52
0001 #include "DataFormats/Provenance/interface/ProductDescription.h"
0002 #include "DataFormats/Provenance/interface/BranchKey.h"
0003 #include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
0004 #include "FWCore/Utilities/interface/EDMException.h"
0005 #include "FWCore/Framework/interface/SignallingProductRegistryFiller.h"
0006
0007 #include "processEDAliases.h"
0008
0009 #include <map>
0010
0011 namespace edm {
0012 namespace {
0013 void checkAndInsertAlias(std::string const& friendlyClassName,
0014 std::string const& moduleLabel,
0015 std::string const& productInstanceName,
0016 std::string const& processName,
0017 std::string const& alias,
0018 std::string const& instanceAlias,
0019 ProductRegistry const& preg,
0020 std::multimap<BranchKey, BranchKey>& aliasMap,
0021 std::map<BranchKey, BranchKey>& aliasKeys) {
0022 std::string const star("*");
0023
0024 BranchKey key(friendlyClassName, moduleLabel, productInstanceName, processName);
0025 if (preg.productList().find(key) == preg.productList().end()) {
0026
0027
0028 for (auto const& product : preg.productList()) {
0029 if (moduleLabel == product.first.moduleLabel() && processName == product.first.processName()) {
0030 throw Exception(errors::Configuration, "EDAlias does not match data\n")
0031 << "There are no products of type '" << friendlyClassName << "'\n"
0032 << "with module label '" << moduleLabel << "' and instance name '" << productInstanceName << "'.\n";
0033 }
0034 }
0035 }
0036
0037 if (auto iter = aliasMap.find(key); iter != aliasMap.end()) {
0038
0039 if (iter->second.moduleLabel() == alias) {
0040 throw Exception(errors::Configuration, "EDAlias conflict\n")
0041 << "The module label alias '" << alias << "' is used for multiple products of type '" << friendlyClassName
0042 << "' with module label '" << moduleLabel << "' and instance name '" << productInstanceName
0043 << "'. One alias has the instance name '" << iter->first.productInstanceName()
0044 << "' and the other has the instance name '" << instanceAlias << "'.";
0045 }
0046 }
0047
0048 std::string const& theInstanceAlias(instanceAlias == star ? productInstanceName : instanceAlias);
0049 BranchKey aliasKey(friendlyClassName, alias, theInstanceAlias, processName);
0050 if (auto it = preg.productList().find(aliasKey); it != preg.productList().end()) {
0051
0052 if (not it->second.isAlias()) {
0053 throw Exception(errors::Configuration, "EDAlias conflicts with data\n")
0054 << "A product of type '" << friendlyClassName << "'\n"
0055 << "with module label '" << alias << "' and instance name '" << theInstanceAlias << "'\n"
0056 << "already exists.\n";
0057 }
0058 return;
0059 }
0060 auto iter = aliasKeys.find(aliasKey);
0061 if (iter != aliasKeys.end()) {
0062
0063 if (iter->second != key) {
0064 throw Exception(errors::Configuration, "EDAlias conflict\n")
0065 << "The module label alias '" << alias << "' and product instance alias '" << theInstanceAlias << "'\n"
0066 << "are used for multiple products of type '" << friendlyClassName << "'\n"
0067 << "One has module label '" << moduleLabel << "' and product instance name '" << productInstanceName
0068 << "',\n"
0069 << "the other has module label '" << iter->second.moduleLabel() << "' and product instance name '"
0070 << iter->second.productInstanceName() << "'.\n";
0071 }
0072 } else {
0073 auto prodIter = preg.productList().find(key);
0074 if (prodIter != preg.productList().end()) {
0075 if (!prodIter->second.produced()) {
0076 throw Exception(errors::Configuration, "EDAlias\n")
0077 << "The module label alias '" << alias << "' and product instance alias '" << theInstanceAlias << "'\n"
0078 << "are used for a product of type '" << friendlyClassName << "'\n"
0079 << "with module label '" << moduleLabel << "' and product instance name '" << productInstanceName
0080 << "',\n"
0081 << "An EDAlias can only be used for products produced in the current process. This one is not.\n";
0082 }
0083 aliasMap.insert(std::make_pair(key, aliasKey));
0084 aliasKeys.insert(std::make_pair(aliasKey, key));
0085 }
0086 }
0087 }
0088 }
0089
0090 namespace detail {
0091 void processEDAliases(std::vector<std::string> const& aliasNamesToProcess,
0092 std::unordered_set<std::string> const& aliasModulesToProcess,
0093 ParameterSet const& proc_pset,
0094 std::string const& processName,
0095 SignallingProductRegistryFiller& preg) {
0096 if (aliasNamesToProcess.empty()) {
0097 return;
0098 }
0099 std::string const star("*");
0100 std::string const empty("");
0101 ParameterSetDescription desc;
0102 desc.add<std::string>("type");
0103 desc.add<std::string>("fromProductInstance", star);
0104 desc.add<std::string>("toProductInstance", star);
0105
0106 std::multimap<BranchKey, BranchKey> aliasMap;
0107
0108 std::map<BranchKey, BranchKey> aliasKeys;
0109
0110
0111 std::multimap<std::string, BranchKey> moduleLabelToBranches;
0112 for (auto const& prod : preg.registry().productList()) {
0113 if (processName == prod.second.processName()) {
0114 moduleLabelToBranches.emplace(prod.first.moduleLabel(), prod.first);
0115 }
0116 }
0117
0118
0119 for (std::string const& alias : aliasNamesToProcess) {
0120 ParameterSet const& aliasPSet = proc_pset.getParameterSet(alias);
0121 std::vector<std::string> vPSetNames = aliasPSet.getParameterNamesForType<VParameterSet>();
0122 for (std::string const& moduleLabel : vPSetNames) {
0123 if (not aliasModulesToProcess.empty() and
0124 aliasModulesToProcess.find(moduleLabel) == aliasModulesToProcess.end()) {
0125 continue;
0126 }
0127
0128 VParameterSet vPSet = aliasPSet.getParameter<VParameterSet>(moduleLabel);
0129 for (ParameterSet& pset : vPSet) {
0130 desc.validate(pset);
0131 std::string friendlyClassName = pset.getParameter<std::string>("type");
0132 std::string productInstanceName = pset.getParameter<std::string>("fromProductInstance");
0133 std::string instanceAlias = pset.getParameter<std::string>("toProductInstance");
0134
0135 if (friendlyClassName == star) {
0136 bool processHasLabel = false;
0137 bool match = false;
0138 for (auto it = moduleLabelToBranches.lower_bound(moduleLabel);
0139 it != moduleLabelToBranches.end() && it->first == moduleLabel;
0140 ++it) {
0141 processHasLabel = true;
0142 if (productInstanceName != star and productInstanceName != it->second.productInstanceName()) {
0143 continue;
0144 }
0145 match = true;
0146
0147 checkAndInsertAlias(it->second.friendlyClassName(),
0148 moduleLabel,
0149 it->second.productInstanceName(),
0150 processName,
0151 alias,
0152 instanceAlias,
0153 preg.registry(),
0154 aliasMap,
0155 aliasKeys);
0156 }
0157 if (not match and processHasLabel) {
0158
0159
0160
0161
0162 throw Exception(errors::Configuration, "EDAlias parameter set mismatch\n")
0163 << "There are no products with module label '" << moduleLabel << "' and product instance name '"
0164 << productInstanceName << "'.\n";
0165 }
0166 } else if (productInstanceName == star) {
0167 bool match = false;
0168 BranchKey lowerBound(friendlyClassName, moduleLabel, empty, empty);
0169 for (ProductRegistry::ProductList::const_iterator it =
0170 preg.registry().productList().lower_bound(lowerBound);
0171 it != preg.registry().productList().end() && it->first.friendlyClassName() == friendlyClassName &&
0172 it->first.moduleLabel() == moduleLabel;
0173 ++it) {
0174 if (it->first.processName() != processName) {
0175 continue;
0176 }
0177 match = true;
0178
0179 checkAndInsertAlias(friendlyClassName,
0180 moduleLabel,
0181 it->first.productInstanceName(),
0182 processName,
0183 alias,
0184 instanceAlias,
0185 preg.registry(),
0186 aliasMap,
0187 aliasKeys);
0188 }
0189 if (!match) {
0190
0191
0192 for (auto const& product : preg.registry().productList()) {
0193 if (moduleLabel == product.first.moduleLabel() && processName == product.first.processName()) {
0194 throw Exception(errors::Configuration, "EDAlias parameter set mismatch\n")
0195 << "There are no products of type '" << friendlyClassName << "'\n"
0196 << "with module label '" << moduleLabel << "'.\n";
0197 }
0198 }
0199 }
0200 } else {
0201 checkAndInsertAlias(friendlyClassName,
0202 moduleLabel,
0203 productInstanceName,
0204 processName,
0205 alias,
0206 instanceAlias,
0207 preg.registry(),
0208 aliasMap,
0209 aliasKeys);
0210 }
0211 }
0212 }
0213 }
0214
0215
0216 for (auto const& aliasEntry : aliasMap) {
0217
0218 ProductRegistry::ProductList::const_iterator it = preg.registry().productList().find(aliasEntry.first);
0219 assert(it != preg.registry().productList().end());
0220 preg.addLabelAlias(it->second, aliasEntry.second.moduleLabel(), aliasEntry.second.productInstanceName());
0221 }
0222 }
0223 }
0224 }