Back to home page

Project CMSSW displayed by LXR

 
 

    


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