Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:28:51

0001 #ifndef FWCore_ParameterSet_ParameterDescriptionNode_h
0002 #define FWCore_ParameterSet_ParameterDescriptionNode_h
0003 
0004 // This is a base class for the class that describes
0005 // the parameters that are allowed or required to be
0006 // in a ParameterSet.  It is also a base class for
0007 // other more complex logical structures which describe
0008 // which combinations of parameters are allowed to be
0009 // in a ParameterSet.
0010 
0011 #include "FWCore/Utilities/interface/value_ptr.h"
0012 
0013 #include <string>
0014 #include <set>
0015 #include <iosfwd>
0016 #include <memory>
0017 
0018 namespace edm {
0019 
0020   class ParameterSet;
0021   template <typename T>
0022   class ParameterDescriptionCases;
0023   class DocFormatHelper;
0024 
0025   // Originally these were defined such that the values were the
0026   // same as in the ParameterSet Entry class and the validation
0027   // depended on that.  But at the moment I'm typing this comment,
0028   // the code no longer depends on the values being the same (which
0029   // is probably good because nothing enforces the correspondence,
0030   // a task for the future when someone has free time would be
0031   // to define the values in a common header, but that would involve
0032   // significant changes to ParameterSet ...)
0033   enum ParameterTypes {
0034     k_int32 = 'I',
0035     k_vint32 = 'i',
0036     k_uint32 = 'U',
0037     k_vuint32 = 'u',
0038     k_int64 = 'L',
0039     k_vint64 = 'l',
0040     k_uint64 = 'X',
0041     k_vuint64 = 'x',
0042     k_double = 'D',
0043     k_vdouble = 'd',
0044     k_bool = 'B',
0045     k_string = 'S',
0046     k_vstring = 's',
0047     k_EventID = 'E',
0048     k_VEventID = 'e',
0049     k_LuminosityBlockID = 'M',
0050     k_VLuminosityBlockID = 'm',
0051     k_InputTag = 't',
0052     k_VInputTag = 'v',
0053     k_ESInputTag = 'g',
0054     k_VESInputTag = 'G',
0055     k_FileInPath = 'F',
0056     k_LuminosityBlockRange = 'A',
0057     k_VLuminosityBlockRange = 'a',
0058     k_EventRange = 'R',
0059     k_VEventRange = 'r',
0060     k_PSet = 'Q',
0061     k_VPSet = 'q'
0062   };
0063 
0064   std::string parameterTypeEnumToString(ParameterTypes iType);
0065 
0066   struct ParameterTypeToEnum {
0067     template <class T>
0068     static ParameterTypes toEnum();
0069   };
0070 
0071   class Comment {
0072   public:
0073     Comment();
0074     explicit Comment(std::string const& iComment);
0075     explicit Comment(char const* iComment);
0076     std::string const& comment() const { return comment_; }
0077 
0078   private:
0079     std::string comment_;
0080   };
0081 
0082   class ParameterDescriptionNode {
0083   public:
0084     ParameterDescriptionNode() {}
0085 
0086     explicit ParameterDescriptionNode(Comment const& iComment) : comment_(iComment.comment()) {}
0087 
0088     virtual ~ParameterDescriptionNode();
0089 
0090     virtual ParameterDescriptionNode* clone() const = 0;
0091 
0092     std::string const& comment() const { return comment_; }
0093     void setComment(std::string const& value);
0094     void setComment(char const* value);
0095 
0096     // The validate function should do one of three things, find that the
0097     // node "exists", make the node "exist" by inserting missing parameters
0098     // or throw.  The only exception to this rule occurs when the argument
0099     // named "optional" is true, which should only be possible for the
0100     // top level nodes of a ParameterSetDescription.  When a parameter is
0101     // found or inserted its label is added into the list of validatedLabels.
0102     void validate(ParameterSet& pset, std::set<std::string>& validatedLabels, bool optional) const {
0103       validate_(pset, validatedLabels, optional);
0104     }
0105 
0106     // As long as it has default values, this will attempt to write
0107     // parameters associated with a node into a cfi file that is
0108     // being automatically generated.  It is quite possible for
0109     // to produce a cfi that will fail validation.  In some cases,
0110     // this will imply the user is required to supply certain missing
0111     // parameters that do not appear in the cfi and do not have defaults
0112     // in the description.  It is also possible to create a pathological
0113     // ParameterSetDescription where the algorithm fails to write
0114     // a valid cfi, in some cases the description can be so pathological
0115     // that it is impossible to write a cfi that will pass validation.
0116     void writeCfi(std::ostream& os, bool optional, bool& startWithComma, int indentation, bool& wroteSomething) const {
0117       writeCfi_(os, optional, startWithComma, indentation, wroteSomething);
0118     }
0119 
0120     // Print out the description in human readable format
0121     void print(std::ostream& os, bool optional, bool writeToCfi, DocFormatHelper& dfh) const;
0122 
0123     bool hasNestedContent() const { return hasNestedContent_(); }
0124 
0125     void printNestedContent(std::ostream& os, bool optional, DocFormatHelper& dfh) const;
0126 
0127     // The next three functions are only called by the logical nodes
0128     // on their subnodes.  When executing these functions, the
0129     // insertion of missing parameters does not occur.
0130 
0131     // Usually checks to see if a parameter exists in the configuration, but
0132     // if the node is a logical node, then it returns the value of the logical
0133     // expression.
0134     bool exists(ParameterSet const& pset) const { return exists_(pset); }
0135 
0136     // For most nodes, this simply returns the same value as the exists
0137     // function.  But for AND nodes this returns true if either its subnodes
0138     // exists.  Used by operator&& during validation, if either of an AND node's
0139     // subnodes exists, then both subnodes get validated.
0140     bool partiallyExists(ParameterSet const& pset) const { return partiallyExists_(pset); }
0141 
0142     // For most nodes, this simply returns the same value as the exists
0143     // function. It is different for an XOR node.  It counts
0144     // XOR subnodes whose exists function returns true.  And it
0145     // does this recursively into XOR nodes that are contained in
0146     // other XOR nodes.
0147     // Used by operator^ during validation:
0148     // -- if it returns more than 1, then validation will throw,
0149     // -- if it returns exactly one, then only the nonzero subnode gets validated
0150     // -- if it returns zero, then validation tries to validate the first node and
0151     // then rechecks to see what the missing parameter insertion did (there could
0152     // be side effects on the nodes that were not validated)
0153     int howManyXORSubNodesExist(ParameterSet const& pset) const { return howManyXORSubNodesExist_(pset); }
0154 
0155     /* Validation puts requirements on which parameters can and cannot exist
0156     within a ParameterSet.  The evaluation of whether a ParameterSet passes
0157     or fails the rules in the ParameterSetDescription is complicated by
0158     the fact that we allow missing parameters to be injected into the
0159     ParameterSet during validation.  One must worry whether injecting a
0160     missing parameter invalidates some other part of the ParameterSet that
0161     was already checked and determined to be OK.  The following restrictions
0162     avoid that problem.
0163 
0164         - The same parameter labels cannot occur in different nodes of the
0165         same ParameterSetDescription.  There are two exceptions to this.
0166         Nodes that are contained in the cases of a ParameterSwitch or the
0167         subnodes of an "exclusive or" are allowed to use the same labels.
0168 
0169         - If insertion is necessary to make an "exclusive or" node pass
0170         validation, then the insertion could make more than one of the
0171         possibilities evaluate true.  This must be checked for after the
0172         insertions occur. The behavior is to throw a Configuration exception
0173         if this problem is encountered. (Example: (A && B) ^ (A && C) where
0174         C already exists in the ParameterSet but A and B do not.  A and B
0175         get inserted by the algorithm, because it tries to make the first
0176         possibility true when all fail without insertion.  Then both
0177         parts of the "exclusive or" pass, which is a validation failure).
0178 
0179         - Another potential problem is that a parameter insertion related
0180         to one ParameterDescription could match unrelated wildcards causing
0181         other validation requirements to change from being passing to failing
0182         or vice versa.  This makes it almost impossible to determine if a
0183         ParameterSet passes validation.  Each time you try to loop through
0184         and check, the result of validation could change.  To avoid this problem,
0185         a list is maintained of the type for all wildcards.  Another list is
0186         maintained for the type of all parameters.  As new items are added
0187         we check for collisions.  The function that builds the ParameterSetDescription,
0188         will throw if this rule is violated.  At the moment, the criteria
0189         for a collision is matching types between a parameter and a wildcard.
0190         (This criteria is overrestrictive.  With some additional CPU and
0191         code development the restriction could be loosened to parameters that
0192         might be injected cannot match the type, trackiness, and wildcard label
0193         pattern of any wildcard that requires a match.  And further this
0194         could not apply to wildcards on different branches of a ParameterSwitch
0195         or "exclusive or".)
0196 
0197     These restrictions have the additional benefit that the things they prohibit
0198     would tend to confuse a user trying to configure a module or a module developer
0199     writing the code to extract the parameters from a ParameterSet.  These rules
0200     tend to prohibit bad design.
0201 
0202     One strategy to avoid problems with wildcard parameters is to add a nested
0203     ParameterSet and put the wildcard parameters in the nested ParameterSet.
0204     The names and types in a nested ParameterSet will not interfere with names
0205     in the containing ParameterSet.
0206     */
0207     void checkAndGetLabelsAndTypes(std::set<std::string>& usedLabels,
0208                                    std::set<ParameterTypes>& parameterTypes,
0209                                    std::set<ParameterTypes>& wildcardTypes) const {
0210       checkAndGetLabelsAndTypes_(usedLabels, parameterTypes, wildcardTypes);
0211     }
0212 
0213     static void printSpaces(std::ostream& os, int n);
0214 
0215   protected:
0216     virtual void checkAndGetLabelsAndTypes_(std::set<std::string>& usedLabels,
0217                                             std::set<ParameterTypes>& parameterTypes,
0218                                             std::set<ParameterTypes>& wildcardTypes) const = 0;
0219 
0220     virtual void validate_(ParameterSet& pset, std::set<std::string>& validatedLabels, bool optional) const = 0;
0221 
0222     virtual void writeCfi_(
0223         std::ostream& os, bool optional, bool& startWithComma, int indentation, bool& wroteSomething) const = 0;
0224 
0225     virtual void print_(std::ostream&, bool /*optional*/, bool /*writeToCfi*/, DocFormatHelper&) const {}
0226 
0227     virtual bool hasNestedContent_() const { return false; }
0228 
0229     virtual void printNestedContent_(std::ostream&, bool /*optional*/, DocFormatHelper&) const {}
0230 
0231     virtual bool exists_(ParameterSet const& pset) const = 0;
0232 
0233     virtual bool partiallyExists_(ParameterSet const& pset) const = 0;
0234 
0235     virtual int howManyXORSubNodesExist_(ParameterSet const& pset) const = 0;
0236 
0237     std::string comment_;
0238   };
0239 
0240   template <>
0241   struct value_ptr_traits<ParameterDescriptionNode> {
0242     static ParameterDescriptionNode* clone(ParameterDescriptionNode const* p) { return p->clone(); }
0243     static void destroy(ParameterDescriptionNode* p) { delete p; }
0244   };
0245 
0246   // operator>> ---------------------------------------------
0247 
0248   std::unique_ptr<ParameterDescriptionCases<bool> > operator>>(bool caseValue, ParameterDescriptionNode const& node);
0249 
0250   std::unique_ptr<ParameterDescriptionCases<int> > operator>>(int caseValue, ParameterDescriptionNode const& node);
0251 
0252   std::unique_ptr<ParameterDescriptionCases<std::string> > operator>>(std::string const& caseValue,
0253                                                                       ParameterDescriptionNode const& node);
0254 
0255   std::unique_ptr<ParameterDescriptionCases<std::string> > operator>>(char const* caseValue,
0256                                                                       ParameterDescriptionNode const& node);
0257 
0258   std::unique_ptr<ParameterDescriptionCases<bool> > operator>>(bool caseValue,
0259                                                                std::unique_ptr<ParameterDescriptionNode> node);
0260 
0261   std::unique_ptr<ParameterDescriptionCases<int> > operator>>(int caseValue,
0262                                                               std::unique_ptr<ParameterDescriptionNode> node);
0263 
0264   std::unique_ptr<ParameterDescriptionCases<std::string> > operator>>(std::string const& caseValue,
0265                                                                       std::unique_ptr<ParameterDescriptionNode> node);
0266 
0267   std::unique_ptr<ParameterDescriptionCases<std::string> > operator>>(char const* caseValue,
0268                                                                       std::unique_ptr<ParameterDescriptionNode> node);
0269 
0270   // operator&& ---------------------------------------------
0271 
0272   std::unique_ptr<ParameterDescriptionNode> operator&&(ParameterDescriptionNode const& node_left,
0273                                                        ParameterDescriptionNode const& node_right);
0274 
0275   std::unique_ptr<ParameterDescriptionNode> operator&&(std::unique_ptr<ParameterDescriptionNode> node_left,
0276                                                        ParameterDescriptionNode const& node_right);
0277 
0278   std::unique_ptr<ParameterDescriptionNode> operator&&(ParameterDescriptionNode const& node_left,
0279                                                        std::unique_ptr<ParameterDescriptionNode> node_right);
0280 
0281   std::unique_ptr<ParameterDescriptionNode> operator&&(std::unique_ptr<ParameterDescriptionNode> node_left,
0282                                                        std::unique_ptr<ParameterDescriptionNode> node_right);
0283 
0284   // operator|| ---------------------------------------------
0285 
0286   std::unique_ptr<ParameterDescriptionNode> operator||(ParameterDescriptionNode const& node_left,
0287                                                        ParameterDescriptionNode const& node_right);
0288 
0289   std::unique_ptr<ParameterDescriptionNode> operator||(std::unique_ptr<ParameterDescriptionNode> node_left,
0290                                                        ParameterDescriptionNode const& node_right);
0291 
0292   std::unique_ptr<ParameterDescriptionNode> operator||(ParameterDescriptionNode const& node_left,
0293                                                        std::unique_ptr<ParameterDescriptionNode> node_right);
0294 
0295   std::unique_ptr<ParameterDescriptionNode> operator||(std::unique_ptr<ParameterDescriptionNode> node_left,
0296                                                        std::unique_ptr<ParameterDescriptionNode> node_right);
0297 
0298   // operator^  ---------------------------------------------
0299 
0300   std::unique_ptr<ParameterDescriptionNode> operator^(ParameterDescriptionNode const& node_left,
0301                                                       ParameterDescriptionNode const& node_right);
0302 
0303   std::unique_ptr<ParameterDescriptionNode> operator^(std::unique_ptr<ParameterDescriptionNode> node_left,
0304                                                       ParameterDescriptionNode const& node_right);
0305 
0306   std::unique_ptr<ParameterDescriptionNode> operator^(ParameterDescriptionNode const& node_left,
0307                                                       std::unique_ptr<ParameterDescriptionNode> node_right);
0308 
0309   std::unique_ptr<ParameterDescriptionNode> operator^(std::unique_ptr<ParameterDescriptionNode> node_left,
0310                                                       std::unique_ptr<ParameterDescriptionNode> node_right);
0311 }  // namespace edm
0312 #endif