CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch13/src/FWCore/ParameterSet/interface/ParameterDescriptionNode.h

Go to the documentation of this file.
00001 #ifndef FWCore_ParameterSet_ParameterDescriptionNode_h
00002 #define FWCore_ParameterSet_ParameterDescriptionNode_h
00003 
00004 // This is a base class for the class that describes
00005 // the parameters that are allowed or required to be
00006 // in a ParameterSet.  It is also a base class for
00007 // other more complex logical structures which describe
00008 // which combinations of parameters are allowed to be
00009 // in a ParameterSet. 
00010 
00011 #include "FWCore/Utilities/interface/value_ptr.h"
00012 
00013 #include <string>
00014 #include <set>
00015 #include <iosfwd>
00016 #include <memory>
00017 
00018 namespace edm {
00019 
00020   class ParameterSet;
00021   template <typename T> class ParameterDescriptionCases;
00022   class DocFormatHelper;
00023 
00024   // Originally these were defined such that the values were the
00025   // same as in the ParameterSet Entry class and the validation
00026   // depended on that.  But at the moment I'm typing this comment,
00027   // the code no longer depends on the values being the same (which
00028   // is probably good because nothing enforces the correspondence,
00029   // a task for the future when someone has free time would be
00030   // to define the values in a common header, but that would involve
00031   // significant changes to ParameterSet ...)
00032   enum ParameterTypes {
00033     k_int32 = 'I',
00034     k_vint32 = 'i',
00035     k_uint32 = 'U',
00036     k_vuint32 = 'u',
00037     k_int64 = 'L',
00038     k_vint64 = 'l',
00039     k_uint64 = 'X',
00040     k_vuint64 = 'x',
00041     k_double = 'D',
00042     k_vdouble = 'd',
00043     k_bool = 'B',
00044     k_string = 'S',
00045     k_vstring = 's',
00046     k_EventID = 'E',
00047     k_VEventID = 'e',
00048     k_LuminosityBlockID = 'M',
00049     k_VLuminosityBlockID = 'm',
00050     k_InputTag = 't',
00051     k_VInputTag = 'v',
00052     k_FileInPath = 'F',
00053     k_LuminosityBlockRange = 'A',
00054     k_VLuminosityBlockRange = 'a',
00055     k_EventRange = 'R',
00056     k_VEventRange = 'r',
00057     k_PSet = 'Q',
00058     k_VPSet = 'q'
00059   };
00060 
00061   std::string parameterTypeEnumToString(ParameterTypes iType);
00062 
00063   struct ParameterTypeToEnum {
00064     template <class T>
00065     static ParameterTypes toEnum();
00066   };
00067 
00068 
00069   class ParameterDescriptionNode {
00070 
00071   public:
00072 
00073     virtual ~ParameterDescriptionNode();
00074 
00075     virtual ParameterDescriptionNode* clone() const = 0;
00076 
00077     std::string const& comment() const { return comment_; }
00078     void setComment(std::string const & value);
00079     void setComment(char const* value);
00080 
00081     // The validate function should do one of three things, find that the
00082     // node "exists", make the node "exist" by inserting missing parameters
00083     // or throw.  The only exception to this rule occurs when the argument
00084     // named "optional" is true, which should only be possible for the
00085     // top level nodes of a ParameterSetDescription.  When a parameter is
00086     // found or inserted its label is added into the list of validatedLabels. 
00087     void validate(ParameterSet & pset,
00088                   std::set<std::string> & validatedLabels,
00089                   bool optional) const {
00090       validate_(pset, validatedLabels, optional);
00091     }
00092 
00093     // As long as it has default values, this will attempt to write
00094     // parameters associated with a node into a cfi file that is 
00095     // being automatically generated.  It is quite possible for
00096     // to produce a cfi that will fail validation.  In some cases,
00097     // this will imply the user is required to supply certain missing
00098     // parameters that do not appear in the cfi and do not have defaults
00099     // in the description.  It is also possible to create a pathological
00100     // ParameterSetDescription where the algorithm fails to write
00101     // a valid cfi, in some cases the description can be so pathological
00102     // that it is impossible to write a cfi that will pass validation.
00103     void writeCfi(std::ostream & os,
00104                   bool & startWithComma,
00105                   int indentation,
00106                   bool & wroteSomething) const {
00107       writeCfi_(os, startWithComma, indentation, wroteSomething);
00108     }
00109 
00110     // Print out the description in human readable format
00111     void print(std::ostream & os,
00112                bool optional,
00113                bool writeToCfi,
00114                DocFormatHelper & dfh);
00115 
00116     bool hasNestedContent() {
00117       return hasNestedContent_();
00118     }
00119 
00120     void printNestedContent(std::ostream & os,
00121                             bool optional,
00122                             DocFormatHelper & dfh);
00123 
00124     // The next three functions are only called by the logical nodes
00125     // on their subnodes.  When executing these functions, the
00126     // insertion of missing parameters does not occur.
00127 
00128     // Usually checks to see if a parameter exists in the configuration, but
00129     // if the node is a logical node, then it returns the value of the logical
00130     // expression. 
00131     bool exists(ParameterSet const& pset) const {
00132       return exists_(pset);
00133     }
00134 
00135     // For most nodes, this simply returns the same value as the exists
00136     // function.  But for AND nodes this returns true if either its subnodes
00137     // exists.  Used by operator&& during validation, if either of an AND node's
00138     // subnodes exists, then both subnodes get validated.
00139     bool partiallyExists(ParameterSet const& pset) const {
00140       return partiallyExists_(pset);
00141     }
00142 
00143     // For most nodes, this simply returns the same value as the exists
00144     // function. It is different for an XOR node.  It counts
00145     // XOR subnodes whose exists function returns true.  And it
00146     // does this recursively into XOR nodes that are contained in
00147     // other XOR nodes.
00148     // Used by operator^ during validation:
00149     // -- if it returns more than 1, then validation will throw,
00150     // -- if it returns exactly one, then only the nonzero subnode gets validated
00151     // -- if it returns zero, then validation tries to validate the first node and
00152     // then rechecks to see what the missing parameter insertion did (there could
00153     // be side effects on the nodes that were not validated)
00154     int howManyXORSubNodesExist(ParameterSet const& pset) const {
00155       return howManyXORSubNodesExist_(pset);
00156     }
00157 
00158     /* Validation puts requirements on which parameters can and cannot exist
00159     within a ParameterSet.  The evaluation of whether a ParameterSet passes
00160     or fails the rules in the ParameterSetDescription is complicated by
00161     the fact that we allow missing parameters to be injected into the
00162     ParameterSet during validation.  One must worry whether injecting a
00163     missing parameter invalidates some other part of the ParameterSet that
00164     was already checked and determined to be OK.  The following restrictions
00165     avoid that problem.
00166 
00167         - The same parameter labels cannot occur in different nodes of the
00168         same ParameterSetDescription.  There are two exceptions to this.
00169         Nodes that are contained in the cases of a ParameterSwitch or the
00170         subnodes of an "exclusive or" are allowed to use the same labels.
00171 
00172         - If insertion is necessary to make an "exclusive or" node pass
00173         validation, then the insertion could make more than one of the
00174         possibilities evaluate true.  This must be checked for after the
00175         insertions occur. The behavior is to throw a Configuration exception
00176         if this problem is encountered.  (Example: (A && B) ^ (A && C) where
00177         C already exists in the ParameterSet but A and B do not.  A and B
00178         get inserted by the algorithm, because it tries to make the first
00179         possibility true when all fail without insertion.  Then both
00180         parts of the "exclusive or" pass, which is a validation failure). 
00181 
00182         - Another potential problem is that a parameter insertion related
00183         to one ParameterDescription could match unrelated wildcards causing
00184         other validation requirements to change from being passing to failing
00185         or vice versa.  This makes it almost impossible to determine if a
00186         ParameterSet passes validation.  Each time you try to loop through
00187         and check, the result of validation could change.  To avoid this problem,
00188         a list is maintained of the type for all wildcards.  Another list is
00189         maintained for the type of all parameters.  As new items are added
00190         we check for collisions.  The function that builds the ParameterSetDescription,
00191         will throw if this rule is violated.  At the moment, the criteria
00192         for a collision is matching types between a parameter and a wildcard.
00193         (This criteria is overrestrictive.  With some additional CPU and
00194         code development the restriction could be loosened to parameters that
00195         might be injected cannot match the type, trackiness, and wildcard label
00196         pattern of any wildcard that requires a match.  And further this
00197         could not apply to wildcards on different branches of a ParameterSwitch
00198         or "exclusive or".)
00199  
00200     These restrictions have the additional benefit that the things they prohibit
00201     would tend to confuse a user trying to configure a module or a module developer
00202     writing the code to extract the parameters from a ParameterSet.  These rules
00203     tend to prohibit bad design.
00204 
00205     One strategy to avoid problems with wildcard parameters is to add a nested
00206     ParameterSet and put the wildcard parameters in the nested ParameterSet.
00207     The names and types in a nested ParameterSet will not interfere with names
00208     in the containing ParameterSet.
00209     */
00210     void checkAndGetLabelsAndTypes(std::set<std::string> & usedLabels,
00211                                    std::set<ParameterTypes> & parameterTypes,
00212                                    std::set<ParameterTypes> & wildcardTypes) const {
00213       checkAndGetLabelsAndTypes_(usedLabels, parameterTypes, wildcardTypes);
00214     }
00215 
00216     static void printSpaces(std::ostream & os, int n);
00217 
00218   protected:
00219 
00220     virtual void checkAndGetLabelsAndTypes_(std::set<std::string> & usedLabels,
00221                                             std::set<ParameterTypes> & parameterTypes,
00222                                             std::set<ParameterTypes> & wildcardTypes) const = 0;
00223 
00224     virtual void validate_(ParameterSet & pset,
00225                            std::set<std::string> & validatedLabels,
00226                            bool optional) const = 0;
00227 
00228     virtual void writeCfi_(std::ostream & os,
00229                            bool & startWithComma,
00230                            int indentation,
00231                            bool & wroteSomething) const = 0;
00232 
00233     virtual void print_(std::ostream & os,
00234                         bool optional,
00235                         bool writeToCfi,
00236                         DocFormatHelper & dfh) { }
00237 
00238     virtual bool hasNestedContent_() {
00239       return false;
00240     }
00241 
00242     virtual void printNestedContent_(std::ostream & os,
00243                                      bool optional,
00244                                      DocFormatHelper & dfh) { }
00245 
00246     virtual bool exists_(ParameterSet const& pset) const = 0;
00247 
00248     virtual bool partiallyExists_(ParameterSet const& pset) const = 0;
00249 
00250     virtual int howManyXORSubNodesExist_(ParameterSet const& pset) const = 0;
00251 
00252     std::string comment_;
00253   };
00254 
00255   template <>
00256   struct value_ptr_traits<ParameterDescriptionNode>
00257   {
00258     static ParameterDescriptionNode * clone( ParameterDescriptionNode const * p ) { return p->clone(); }
00259   };
00260 
00261   // operator>> ---------------------------------------------
00262 
00263   std::auto_ptr<ParameterDescriptionCases<bool> >
00264   operator>>(bool caseValue,
00265              ParameterDescriptionNode const& node);
00266 
00267   std::auto_ptr<ParameterDescriptionCases<int> >
00268   operator>>(int caseValue,
00269              ParameterDescriptionNode const& node);
00270 
00271   std::auto_ptr<ParameterDescriptionCases<std::string> >
00272   operator>>(std::string const& caseValue,
00273              ParameterDescriptionNode const& node);
00274 
00275   std::auto_ptr<ParameterDescriptionCases<std::string> >
00276   operator>>(char const* caseValue,
00277              ParameterDescriptionNode const& node);
00278 
00279   std::auto_ptr<ParameterDescriptionCases<bool> >
00280   operator>>(bool caseValue,
00281              std::auto_ptr<ParameterDescriptionNode> node);
00282 
00283   std::auto_ptr<ParameterDescriptionCases<int> >
00284   operator>>(int caseValue,
00285              std::auto_ptr<ParameterDescriptionNode> node);
00286 
00287   std::auto_ptr<ParameterDescriptionCases<std::string> >
00288   operator>>(std::string const& caseValue,
00289              std::auto_ptr<ParameterDescriptionNode> node);
00290 
00291   std::auto_ptr<ParameterDescriptionCases<std::string> >
00292   operator>>(char const* caseValue,
00293              std::auto_ptr<ParameterDescriptionNode> node);
00294 
00295   // operator&& ---------------------------------------------
00296 
00297   std::auto_ptr<ParameterDescriptionNode>
00298   operator&&(ParameterDescriptionNode const& node_left,
00299              ParameterDescriptionNode const& node_right);
00300 
00301   std::auto_ptr<ParameterDescriptionNode>
00302   operator&&(std::auto_ptr<ParameterDescriptionNode> node_left,
00303              ParameterDescriptionNode const& node_right);
00304 
00305   std::auto_ptr<ParameterDescriptionNode>
00306   operator&&(ParameterDescriptionNode const& node_left,
00307              std::auto_ptr<ParameterDescriptionNode> node_right);
00308 
00309   std::auto_ptr<ParameterDescriptionNode>
00310   operator&&(std::auto_ptr<ParameterDescriptionNode> node_left,
00311              std::auto_ptr<ParameterDescriptionNode> node_right);
00312 
00313   // operator|| ---------------------------------------------
00314 
00315   std::auto_ptr<ParameterDescriptionNode>
00316   operator||(ParameterDescriptionNode const& node_left,
00317              ParameterDescriptionNode const& node_right);
00318 
00319   std::auto_ptr<ParameterDescriptionNode>
00320   operator||(std::auto_ptr<ParameterDescriptionNode> node_left,
00321              ParameterDescriptionNode const& node_right);
00322 
00323   std::auto_ptr<ParameterDescriptionNode>
00324   operator||(ParameterDescriptionNode const& node_left,
00325              std::auto_ptr<ParameterDescriptionNode> node_right);
00326 
00327   std::auto_ptr<ParameterDescriptionNode>
00328   operator||(std::auto_ptr<ParameterDescriptionNode> node_left,
00329              std::auto_ptr<ParameterDescriptionNode> node_right);
00330 
00331   // operator^  ---------------------------------------------
00332 
00333   std::auto_ptr<ParameterDescriptionNode>
00334   operator^(ParameterDescriptionNode const& node_left,
00335             ParameterDescriptionNode const& node_right);
00336 
00337   std::auto_ptr<ParameterDescriptionNode>
00338   operator^(std::auto_ptr<ParameterDescriptionNode> node_left,
00339             ParameterDescriptionNode const& node_right);
00340 
00341   std::auto_ptr<ParameterDescriptionNode>
00342   operator^(ParameterDescriptionNode const& node_left,
00343             std::auto_ptr<ParameterDescriptionNode> node_right);
00344 
00345   std::auto_ptr<ParameterDescriptionNode>
00346   operator^(std::auto_ptr<ParameterDescriptionNode> node_left,
00347             std::auto_ptr<ParameterDescriptionNode> node_right);
00348 }
00349 #endif