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