CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/DataFormats/Common/src/RefCore.cc

Go to the documentation of this file.
00001 #include "DataFormats/Common/interface/RefCore.h"
00002 #include "FWCore/Utilities/interface/EDMException.h"
00003 #include "FWCore/Utilities/interface/TypeID.h"
00004 #include <cassert>
00005 #include <iostream>
00006 #include <ostream>
00007 
00008 static
00009 void throwInvalidRefFromNullOrInvalidRef(const edm::TypeID& id) {
00010   throw edm::Exception(edm::errors::InvalidReference,
00011                   "BadRefCore")
00012   << "RefCore: Request to resolve a null or invalid reference to a product of type '"
00013   << id
00014         << "' has been detected.\n"
00015   << "Please modify the calling code to test validity before dereferencing.\n";  
00016 }
00017 
00018 static
00019 void throwInvalidRefFromNoCache(const edm::TypeID& id, edm::ProductID const& prodID) {
00020   throw edm::Exception(edm::errors::InvalidReference,
00021                   "BadRefCore")
00022   << "RefCore: A request to resolve a reference to a product of type '"
00023   << id
00024   << "' with ProductID '" << prodID
00025         << "' cannot be satisfied.\n"
00026         << "The reference has neither a valid product pointer nor an EDProductGetter.\n"
00027         << "The calling code must be modified to establish a functioning EDProducterGetter\n"
00028   << "for the context in which this call is mode\n";
00029   
00030 }
00031 
00032 namespace edm {
00033 
00034   RefCore::RefCore(ProductID const& theId, void const* prodPtr, EDProductGetter const* prodGetter, bool transient) :
00035       cachePtr_(prodPtr?prodPtr:prodGetter),
00036       processIndex_(theId.processIndex()),
00037       productIndex_(theId.productIndex()),
00038       transient_(transient,prodPtr!=0 || prodGetter==0)
00039       {}
00040 
00041   EDProduct const*
00042   RefCore::getProductPtr(std::type_info const& type) const {
00043     // The following invariant would be nice to establish in all
00044     // constructors, but we can not be sure that the context in which
00045     // EDProductGetter::instance() is called will be one where a
00046     // non-null pointer is returned. The biggest question in the
00047     // various times at which Root makes RefCore instances, and how
00048     // old ones might be recycled.
00049     //
00050     // If our ProductID is non-null, we must have a way to get at the
00051     // product (unless it has been dropped). This means either we
00052     // already have the pointer to the product, or we have a valid
00053     // EDProductGetter to use.
00054     //
00055     //     assert(!id_.isValid() || productGetter() || prodPtr_);
00056 
00057     ProductID tId = id();
00058     assert (!isTransient());
00059     if (!tId.isValid()) {
00060       throwInvalidRefFromNullOrInvalidRef(TypeID(type));
00061     }
00062 
00063     //if (productPtr() == 0 && productGetter() == 0) {
00064     if (cachePtr_ == 0) {
00065       throwInvalidRefFromNoCache(TypeID(type),tId);
00066     }
00067     EDProduct const* product = productGetter()->getIt(tId);
00068     if ( 0 == product) {
00069       productNotFoundException(type);
00070     }
00071     return product;
00072   }
00073 
00074   void
00075   RefCore::productNotFoundException(std::type_info const& type) const {
00076     throw edm::Exception(errors::ProductNotFound)
00077       << "RefCore: A request to resolve a reference to a product of type '"
00078       << TypeID(type)
00079       << "' with ProductID '" << id() << "'"
00080       << "\ncan not be satisfied because the product cannot be found."
00081       << "\nProbably the branch containing the product is not stored in the input file.\n";
00082   }
00083 
00084   void
00085   RefCore::wrongTypeException(std::type_info const& expectedType, std::type_info const& actualType) const {
00086     throw edm::Exception(errors::InvalidReference,"WrongType")
00087         << "RefCore: A request to convert a contained product of type '"
00088         << TypeID(actualType) << "'\n"
00089         << " to type '" << TypeID(expectedType) << "'"
00090         << "\nfor ProductID '" << id()
00091         << "' can not be satisfied\n";
00092   }
00093 
00094   void
00095   RefCore::nullPointerForTransientException(std::type_info const& type) const {
00096     throw edm::Exception(errors::InvalidReference)
00097         << "RefCore: A request to resolve a transient reference to a product of type: "
00098         << TypeID(type)
00099         << "\ncan not be satisfied because the pointer to the product is null.\n";
00100   }
00101 
00102   bool
00103   RefCore::isAvailable() const {
00104     ProductID tId = id();
00105     return productPtr() != 0 || (tId.isValid() && productGetter() != 0 && 0 != productGetter()->getIt(tId));
00106   }
00107 
00108   void
00109   RefCore::setProductGetter(EDProductGetter const* prodGetter) const {
00110     cachePtr_ = prodGetter;
00111     setCacheIsProductPtr(false);
00112   }
00113 
00114   void
00115   RefCore::pushBackItem(RefCore const& productToBeInserted, bool checkPointer) {
00116     if (productToBeInserted.isNull() && !productToBeInserted.isTransient()) {
00117       throw edm::Exception(errors::InvalidReference,"Inconsistency")
00118         << "RefCore::pushBackItem: Ref or Ptr has invalid (zero) product ID, so it cannot be added to RefVector (PtrVector). "
00119         << "id should be (" << id() << ")\n";
00120     }
00121     if (isNonnull()) {
00122       if (isTransient() != productToBeInserted.isTransient()) {
00123         if (productToBeInserted.isTransient()) {
00124           throw edm::Exception(errors::InvalidReference,"Inconsistency")
00125             << "RefCore::pushBackItem: Transient Ref or Ptr cannot be added to persistable RefVector (PtrVector). "
00126             << "id should be (" << id() << ")\n";
00127         } else {
00128           throw edm::Exception(errors::InvalidReference,"Inconsistency")
00129             << "RefCore::pushBackItem: Persistable Ref or Ptr cannot be added to transient RefVector (PtrVector). "
00130             << "id is (" << productToBeInserted.id() << ")\n";
00131         }
00132       }
00133       if (!productToBeInserted.isTransient() && id() != productToBeInserted.id()) {
00134         throw edm::Exception(errors::InvalidReference,"Inconsistency")
00135           << "RefCore::pushBackItem: Ref or Ptr is inconsistent with RefVector (PtrVector)"
00136           << "id = (" << productToBeInserted.id() << ") should be (" << id() << ")\n";
00137       }
00138       if (productToBeInserted.isTransient() && checkPointer && productToBeInserted.isNonnull() && productToBeInserted != *this) {
00139         throw edm::Exception(errors::InvalidReference,"Inconsistency")
00140            << "RefCore::pushBackItem: Ref points into different collection than the RefVector.\n";
00141       }
00142     } else {
00143       if (productToBeInserted.isTransient()) {
00144         setTransient();
00145       }
00146       if (productToBeInserted.isNonnull()) {
00147         setId(productToBeInserted.id());
00148       }
00149     }
00150     //Since productPtr and productGetter actually share the same pointer internally,
00151     // we want to be sure that if the productPtr is set we use that one and only if
00152     // it isn't set do we set the productGetter if available
00153     if (productPtr() == 0 && productToBeInserted.productPtr() != 0) {
00154       setProductPtr(productToBeInserted.productPtr());
00155     } else if (productPtr() == 0 && productGetter() == 0 && productToBeInserted.productGetter() != 0) {
00156       setProductGetter(productToBeInserted.productGetter());
00157     }
00158   }
00159   
00160 }