00001
00011 #include "DataFormats/Provenance/interface/ProductRegistry.h"
00012 #include "DataFormats/Provenance/interface/BranchType.h"
00013 #include "FWCore/Utilities/interface/ReflexTools.h"
00014 #include "FWCore/Utilities/interface/Exception.h"
00015 #include "FWCore/Utilities/interface/TypeID.h"
00016 #include "FWCore/Utilities/interface/WrappedClassName.h"
00017 #include <algorithm>
00018 #include <sstream>
00019
00020 namespace edm {
00021 namespace {
00022 void checkDicts(BranchDescription const& productDesc) {
00023 if (productDesc.transient()) {
00024 checkDictionaries(productDesc.fullClassName(), true);
00025 } else {
00026 checkDictionaries(wrappedClassName(productDesc.fullClassName()), false);
00027 }
00028 }
00029 }
00030
00031 ProductRegistry::ProductRegistry() :
00032 productList_(),
00033 nextID_(1),
00034 transients_() {
00035 }
00036
00037 ProductRegistry::Transients::Transients() :
00038 frozen_(false),
00039 constProductList_(),
00040 productLookup_(),
00041 elementLookup_() {
00042 }
00043
00044 ProductRegistry::ProductRegistry(ProductList const& productList, unsigned int nextID) :
00045 productList_(productList),
00046 nextID_(nextID),
00047 transients_() {
00048 frozen() = true;
00049 }
00050
00051 void
00052 ProductRegistry::addProduct(BranchDescription const& productDesc,
00053 bool fromListener) {
00054 assert(productDesc.produced());
00055 throwIfFrozen();
00056 productDesc.init();
00057 checkDicts(productDesc);
00058 productList_.insert(std::make_pair(BranchKey(productDesc), productDesc));
00059 addCalled(productDesc,fromListener);
00060 }
00061
00062 void
00063 ProductRegistry::copyProduct(BranchDescription const& productDesc) {
00064 assert(!productDesc.produced());
00065 throwIfFrozen();
00066 productDesc.init();
00067 BranchKey k = BranchKey(productDesc);
00068 ProductList::iterator iter = productList_.find(k);
00069 if (iter == productList_.end()) {
00070 productList_.insert(std::make_pair(k, productDesc));
00071 } else {
00072 assert(combinable(iter->second, productDesc));
00073 iter->second.merge(productDesc);
00074 }
00075 }
00076
00077 void
00078 ProductRegistry::setProductIDs(unsigned int startingID) {
00079 throwIfNotFrozen();
00080 if (startingID < nextID_) {
00081 startingID = nextID_;
00082 }
00083 --startingID;
00084 for (ProductList::iterator it = productList_.begin(), itEnd = productList_.end();
00085 it != itEnd; ++it) {
00086 if (it->second.produced() && it->second.branchType() == InEvent) {
00087 it->second.setProductIDtoAssign(ProductID(++startingID));
00088 }
00089 }
00090 setNextID(startingID + 1);
00091 initializeTransients();
00092 }
00093
00094 bool
00095 ProductRegistry::anyProducts(BranchType brType) const {
00096 throwIfNotFrozen();
00097 for (ProductList::const_iterator it = productList_.begin(), itEnd = productList_.end();
00098 it != itEnd; ++it) {
00099 if (it->second.branchType() == brType) {
00100 return true;
00101 }
00102 }
00103 return false;
00104 }
00105
00106 void
00107 ProductRegistry::setFrozen() const {
00108 checkAllDictionaries();
00109 if(frozen()) return;
00110 frozen() = true;
00111 initializeTransients();
00112 }
00113
00114 void
00115 ProductRegistry::throwIfFrozen() const {
00116 if (frozen()) {
00117 throw cms::Exception("ProductRegistry", "throwIfFrozen")
00118 << "cannot modify the ProductRegistry because it is frozen\n";
00119 }
00120 }
00121
00122 void
00123 ProductRegistry::throwIfNotFrozen() const {
00124 if (!frozen()) {
00125 throw cms::Exception("ProductRegistry", "throwIfNotFrozen")
00126 << "cannot read the ProductRegistry because it is not yet frozen\n";
00127 }
00128 }
00129
00130 void
00131 ProductRegistry::addCalled(BranchDescription const&, bool) {
00132 }
00133
00134 std::vector<std::string>
00135 ProductRegistry::allBranchNames() const
00136 {
00137 std::vector<std::string> result;
00138 result.reserve( productList().size() );
00139
00140 ProductList::const_iterator it = productList().begin();
00141 ProductList::const_iterator end = productList().end();
00142
00143 for ( ; it != end; ++it ) result.push_back(it->second.branchName());
00144
00145 return result;
00146 }
00147
00148 std::vector<BranchDescription const*>
00149 ProductRegistry::allBranchDescriptions() const
00150 {
00151 std::vector<BranchDescription const*> result;
00152 result.reserve( productList().size() );
00153
00154 ProductList::const_iterator it = productList().begin();
00155 ProductList::const_iterator end = productList().end();
00156
00157 for ( ; it != end; ++it) result.push_back(&(it->second));
00158 return result;
00159 }
00160
00161 std::string
00162 ProductRegistry::merge(ProductRegistry const& other,
00163 std::string const& fileName,
00164 BranchDescription::MatchMode parametersMustMatch,
00165 BranchDescription::MatchMode branchesMustMatch) {
00166 std::ostringstream differences;
00167
00168 ProductRegistry::ProductList::iterator j = productList_.begin();
00169 ProductRegistry::ProductList::iterator s = productList_.end();
00170 ProductRegistry::ProductList::const_iterator i = other.productList().begin();
00171 ProductRegistry::ProductList::const_iterator e = other.productList().end();
00172
00173
00174 while(j != s || i != e) {
00175 if (j != s && j->second.produced()) {
00176
00177 ++j;
00178 } else if (j == s || i != e && i->first < j->first) {
00179 if (i->second.present()) {
00180 differences << "Branch '" << i->second.branchName() << "' is in file '" << fileName << "'\n";
00181 differences << " but not in previous files.\n";
00182 } else {
00183 productList_.insert(*i);
00184 }
00185 ++i;
00186 } else if (i == e || j != s && j->first < i->first) {
00187 if (branchesMustMatch == BranchDescription::Strict) {
00188 differences << "Branch '" << j->second.branchName() << "' is in previous files\n";
00189 differences << " but not in file '" << fileName << "'.\n";
00190 }
00191 ++j;
00192 } else {
00193 std::string difs = match(j->second, i->second, fileName, parametersMustMatch);
00194 if (difs.empty()) {
00195 if (parametersMustMatch == BranchDescription::Permissive) j->second.merge(i->second);
00196 } else {
00197 differences << difs;
00198 }
00199 ++i;
00200 ++j;
00201 }
00202 }
00203 if (other.nextID() > nextID()) {
00204 setNextID(other.nextID());
00205 setProductIDs(other.nextID());
00206 }
00207 initializeTransients();
00208 return differences.str();
00209 }
00210
00211 void ProductRegistry::initializeTransients() const {
00212 constProductList().clear();
00213 productLookup().clear();
00214 elementLookup().clear();
00215 for (ProductList::const_iterator i = productList_.begin(), e = productList_.end(); i != e; ++i) {
00216 constProductList().insert(std::make_pair(i->first, ConstBranchDescription(i->second)));
00217
00218 ProcessLookup& processLookup = productLookup()[i->first.friendlyClassName_];
00219 std::vector<BranchID>& vint = processLookup[i->first.processName_];
00220 vint.push_back(i->second.branchID());
00221
00222
00223 ROOT::Reflex::Type type(ROOT::Reflex::Type::ByName(i->second.className()));
00224 if (bool(type)) {
00225
00226
00227
00228
00229
00230
00231
00232
00233 ROOT::Reflex::Type valueType;
00234 if ((is_RefVector(type, valueType) ||
00235 is_RefToBaseVector(type, valueType ) ||
00236 value_type_of(type, valueType))
00237 && bool(valueType)) {
00238
00239 fillElementLookup(valueType, i->second.branchID(), i->first);
00240
00241
00242 std::vector<ROOT::Reflex::Type> baseTypes;
00243 public_base_classes(valueType, baseTypes);
00244
00245 for (std::vector<ROOT::Reflex::Type>::iterator iter = baseTypes.begin(),
00246 iend = baseTypes.end();
00247 iter != iend;
00248 ++iter) {
00249 fillElementLookup(*iter, i->second.branchID(), i->first);
00250 }
00251 }
00252 }
00253 }
00254 }
00255
00256 void ProductRegistry::fillElementLookup(const ROOT::Reflex::Type & type,
00257 const BranchID& id,
00258 const BranchKey& bk) const
00259 {
00260 TypeID typeID(type.TypeInfo());
00261 std::string friendlyClassName = typeID.friendlyClassName();
00262
00263 ProcessLookup& processLookup = elementLookup()[friendlyClassName];
00264 std::vector<BranchID>& vint = processLookup[bk.processName_];
00265 vint.push_back(id);
00266 }
00267
00268 void ProductRegistry::print(std::ostream& os) const {
00269 for (ProductList::const_iterator i = productList_.begin(), e = productList_.end(); i != e; ++i) {
00270 os << i->second << "\n-----\n";
00271 }
00272 }
00273
00274 }