CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/DataFormats/Provenance/interface/ProductHolderIndexHelper.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Provenance_ProductHolderIndexHelper_h
00002 #define DataFormats_Provenance_ProductHolderIndexHelper_h
00003 
00054 #include "FWCore/Utilities/interface/ProductHolderIndex.h"
00055 #include "FWCore/Utilities/interface/ProductKindOfType.h"
00056 #include "FWCore/Utilities/interface/TypeID.h"
00057 
00058 #include <iosfwd>
00059 #include <memory>
00060 #include <set>
00061 #include <string>
00062 #include <vector>
00063 
00064 namespace edm {
00065   class TypeWithDict;
00066 
00067   class ProductHolderIndexHelper {
00068   public:
00069 
00070     ProductHolderIndexHelper();
00071 
00072     // The accessors below return a ProductHolderIndex that matches 
00073     // the arguments or a set of matching indexes using the Matches
00074     // class. A returned index can have a value that indicates that it
00075     // is invalid or ambiguous and the client should check for these
00076     // values before using the index (see ProductIndexHolder.h).
00077 
00078     // If no matches are found or the ProductHolderIndexHelper
00079     // has not been frozen yet, then an invalid index or a Matches
00080     // object with numberOfMatches equal to 0 will be returned.
00081 
00082     // The ambiguous values can occur when the kind of type is ELEMENT_TYPE
00083     // type. ELEMENT_TYPE is the type or base type of an object
00084     // stored in a container that is the product. These types are used
00085     // with data requests that use Views. For PRODUCT_TYPE types, ambiguity
00086     // is not possible.
00087 
00088     // The next function returns the index for the one group that
00089     // matches the type, module label, instance, and process.
00090     // The 3 pointer arguments must point to C style strings terminated
00091     // by a '\0' with the one following possible exception. If the
00092     // process pointer is null or the process string empty, then
00093     // this returns the index of the special ProductHolder that
00094     // knows how to search for the product matching the type, module
00095     // label, and instance and which is from the most recent process.
00096     ProductHolderIndex index(KindOfType kindOfType,
00097                              TypeID const& typeID,
00098                              char const* moduleLabel,
00099                              char const* instance,
00100                              char const* process = 0) const;
00101 
00102     class Matches {
00103     public:
00104       Matches(ProductHolderIndexHelper const* productHolderIndexHelper,
00105               unsigned int startInIndexAndNames,
00106               unsigned int numberOfMatches);
00107 
00108       ProductHolderIndex index(unsigned int i) const;
00109       unsigned int numberOfMatches() const { return numberOfMatches_; }
00110       bool isFullyResolved(unsigned int i) const;
00111     private:
00112       ProductHolderIndexHelper const* productHolderIndexHelper_;
00113       unsigned int startInIndexAndNames_;
00114       unsigned int numberOfMatches_;
00115     };
00116 
00117     // Return ProductHolderIndex's for all product holders that
00118     // match the type, module label, and product instance name.
00119     // The pointer arguments must be C style strings terminated
00120     // by a '\0'.
00121     Matches
00122     relatedIndexes(KindOfType kindOfType,
00123                    TypeID const& typeID,
00124                    char const* moduleLabel,
00125                    char const* instance) const;
00126 
00127     // Return indexes for all groups that match the type.
00128     Matches
00129     relatedIndexes(KindOfType kindOfType,
00130                    TypeID const& typeID) const;
00131 
00132     // This will throw if called after the object is frozen.
00133     // The typeID must be for a type with a dictionary
00134     // (the calling function is expected to check that)
00135     // The pointer arguments must point at C style strings
00136     // terminated by '\0'.
00137     // 1. This creates an entry and new ProductHolderIndex for
00138     // the product if it does not already exist. If it
00139     // does exist then it throws.
00140     // 2. If it does not already exist, this will create an
00141     // entry and new ProductHolderIndex for the ProductHolder
00142     // that will search for the matching type, label, and
00143     // instance for the most recent process (internally indicated
00144     // by an empty process string).
00145     // This will then loop over the contained class (if it exists)
00146     // and the base classes of the contained class.
00147     // 1. If the matching type, label, instance, and process
00148     // already exist then that entry is modified and marked
00149     // ambiguous. If not, it inserts an entry which uses the same
00150     // ProductHolderIndex as the containing product.
00151     // 2. If it does not already exist it inserts a new
00152     // entry with a new ProductHolderIndex for the case
00153     // which searches for the most recent process.
00154     ProductHolderIndex
00155     insert(TypeWithDict const& typeWithDict,
00156            char const* moduleLabel,
00157            char const* instance,
00158            char const* process);
00159 
00160     // Before the object is frozen the accessors above will
00161     // fail to find a match. Once frozen, no more new entries
00162     // can be added with insert.
00163     void setFrozen();
00164 
00165     std::vector<std::string> const& lookupProcessNames() const;
00166 
00167     class Range {
00168     public:
00169       Range(unsigned int begin, unsigned int end) : begin_(begin), end_(end) { }
00170       unsigned int begin() const { return begin_; }
00171       unsigned int end() const { return end_; }
00172     private:
00173       unsigned int begin_;
00174       unsigned int end_;
00175     };
00176 
00177     class IndexAndNames {
00178     public:
00179       IndexAndNames(ProductHolderIndex index, unsigned int start, unsigned int startProcess) :
00180         index_(index), startInBigNamesContainer_(start), startInProcessNames_(startProcess) { }
00181       ProductHolderIndex index() const { return index_; }
00182       unsigned int startInBigNamesContainer() const { return startInBigNamesContainer_; }
00183       unsigned int startInProcessNames() const { return startInProcessNames_; }
00184     private:
00185       ProductHolderIndex index_;
00186       unsigned int startInBigNamesContainer_;
00187       unsigned int startInProcessNames_;
00188     };
00189 
00190     unsigned int beginElements() const { return beginElements_; }
00191     std::vector<TypeID> const& sortedTypeIDs() const { return sortedTypeIDs_; }
00192     std::vector<Range> const& ranges() const { return ranges_; }
00193     std::vector<IndexAndNames> const& indexAndNames() const { return indexAndNames_; }
00194     std::vector<char> const& processNames() const { return processNames_; }
00195 
00196     // The next few functions are intended for internal use
00197     // but are public so tests can use them also.
00198 
00199     unsigned int indexToIndexAndNames(KindOfType kindOfType,
00200                                       TypeID const& typeID,
00201                                       char const* moduleLabel,
00202                                       char const* instance,
00203                                       char const* process) const;
00204 
00205     // Returns the index into sortedTypeIDs_. Returns the maximum unsigned
00206     // int value if the type is not there.
00207     unsigned int indexToType(KindOfType kindOfType, TypeID const& typeID) const;
00208 
00209     // Returns the index of the process name in processNames_. Returns the
00210     // maximum unsigned int value if the process name is not found.
00211     unsigned int processIndex(char const* process) const;
00212 
00213     // This will throw if it detects problems, but unless there is a bug
00214     // there should never be any. Mostly it is checking for things which
00215     // might cause out of bounds errors when accessing the vectors.
00216     void sanityCheck() const;
00217 
00218     ProductHolderIndex nextIndexValue() const { return nextIndexValue_; }
00219 
00220     // For debugging only
00221     void print(std::ostream& os) const;
00222 
00223   private:
00224 
00225     // Next available value for a ProductHolderIndex. This just
00226     // increments by one each time a new value is assigned.
00227     ProductHolderIndex nextIndexValue_;
00228 
00229     // This is an index into sortedTypeIDs_ that tells where
00230     // the entries corresponding to types of elements in containers
00231     // start.
00232     unsigned int beginElements_;
00233 
00234     // Sorted by putting all the product entries first and
00235     // then the element entries.  Then sorted by TypeID value.
00236     // Most lookups start here by finding the TypeID and
00237     // then using its position to find the corresponding Range
00238     // in the ranges_ vector below.
00239     std::vector<TypeID> sortedTypeIDs_;
00240 
00241     // There is a one to one correspondence between this vector
00242     // and sortedTypeIDs_ and the corresponding elements appear
00243     // in the same order. Each Range object holds the beginning and
00244     // end of the corresponding elements in the indexAndNames_
00245     // vector below.
00246     std::vector<Range> ranges_;
00247 
00248     // Each element of this vector contains a ProductHolderIndex.
00249     // It also contains indexes into vectors of characters that
00250     // hold the corresponding moduleLabel, instance, and process
00251     // name. Note this is sorted with product entries first then
00252     // element entries, then by TypeID, then by moduleLabel,
00253     // then by instance, and finally by process. Note that in
00254     // a subset of entries that have matching type/label/instance
00255     // the entry with an empty process name will always be the
00256     // first process and startInProcessNames_ will always be 0
00257     // for the empty process name.
00258     std::vector<IndexAndNames> indexAndNames_;
00259 
00260     // These contain C style strings terminated
00261     // by '\0' all concatenated together. In the
00262     // first vector the strings come in pairs,
00263     // always module label then instance.  The pairs
00264     // are ordered the same as the IndexAndNames
00265     // vector. Within a TypeID, the moduleLabel/instance
00266     // pair is not duplicated if it appears multiple times.
00267     // The second vector contains all the process names
00268     // in alphabetical order with no duplication. The
00269     // first element is always the empty string.
00270     std::vector<char> bigNamesContainer_; 
00271     std::vector<char> processNames_;
00272 
00273     // Duplicates the entries in processNames_ in
00274     // a convenient format.
00275     std::vector<std::string> lookupProcessNames_;
00276 
00277     // The rest of the data members are for temporary use
00278     // while the data structure is being filled.
00279 
00280     class Item {
00281     public:
00282       Item(KindOfType kindOfType,
00283            TypeID const& typeID,
00284            std::string const& moduleLabel,
00285            std::string const& instance,
00286            std::string const& process,
00287            ProductHolderIndex index);
00288       KindOfType kindOfType() const { return kindOfType_; }
00289       TypeID const& typeID() const { return typeID_; }
00290       std::string const& moduleLabel() const { return moduleLabel_; }
00291       std::string const& instance() const { return instance_; }
00292       std::string const& process() const { return process_; }
00293       ProductHolderIndex index() const { return index_; }
00294 
00295       void clearProcess() { process_.clear(); }
00296       void setIndex(ProductHolderIndex v) { index_ = v; }
00297 
00298       bool operator<(Item const& right) const;
00299 
00300     private:
00301       KindOfType kindOfType_;
00302       TypeID typeID_;
00303       std::string moduleLabel_;
00304       std::string instance_;
00305       std::string process_;
00306       ProductHolderIndex index_;
00307     };
00308 
00309     std::unique_ptr<std::set<Item> > items_;
00310 
00311     std::unique_ptr<std::set<std::string> > processItems_;
00312   };
00313 }
00314 #endif