Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-10-01 22:40:37

0001 #ifndef FWCore_ParameterSet_PluginDescription_h
0002 #define FWCore_ParameterSet_PluginDescription_h
0003 // -*- C++ -*-
0004 //
0005 // Package:     FWCore/ParameterSet
0006 // Class  :     PluginDescription
0007 //
0008 /**\class PluginDescription PluginDescription.h "PluginDescription.h"
0009 
0010  Description: Use to describe how to validate a plugin that will be loaded
0011 
0012  Usage:
0013  User defined plugins which are constructed by passing a edm::ParameterSet can
0014  have their parameters validated using the \c edm::PluginDescription. For this to
0015  work, one must
0016  
0017  1) Plugin configuration
0018  All the parameters used by the Plugin must be contained within one PSet, this
0019  also includes an cms.string parameter containing the name of the actual plugin
0020  type to be loaded. E.g. if a module \c FooProd loaded a plugin of specific type
0021  \c BarHelper and \c BarHelper uses the parameter named \c value :
0022  \code{.py}
0023  foo = cms.EDProducer("FooProd",
0024                       pluginDescription = cms.PSet(type = cms.string("BarHelper"),
0025                                                    value = cms.int32(5) ) )
0026  \endcode
0027 
0028 2) Plugin fillPSetDescription
0029 Each user plugin must define a static member function:
0030  \code{.cpp}
0031  static void fillPSetDescription(edm::ParameterSetDescription const&);
0032  \endcode
0033 
0034  The function fills the \c edm::ParameterSetDescription with the descriptions of
0035  the parameters necessary for that particular plugin. Note that the parameter
0036  used by the module to find the type of the plugin should NOT be declared in
0037  the \c edm::ParameterSetDescription since it will be added by the
0038  \c edm::PluginDescription itself. E.g.
0039  
0040  \code{.cpp}
0041  void BarHelper::fillPSetDescription(edm::ParameterSetDescription& iPSD) {
0042     iPSD.add<int>("value", 5);
0043  }
0044  \endcode
0045  
0046  3) Module's fillDescriptions
0047  The module which uses the plugins must use the \c edm::PluginDescription within its
0048  \c fillDescriptions static member function.
0049  The \c edm::PluginDescription object is attached to the \c edm::ParameterSetDescription
0050  object which is being used to represent the PSet for the plugin. In turn, that
0051  \c edm::ParamterSetDescription is attached to the module's top level \edm::ParameterSetDescription.
0052  This exactly mimics what would be done if the plugin's parameters were directly known to
0053  the module.
0054  
0055  \code{.cpp}
0056  void FooProd::fillDescriptions(ConfigurationDescriptions& oDesc) {
0057    //specify how to get the plugin validation
0058    ParameterSetDescription pluginDesc;
0059    //'type' is the label to the string containing which plugin to load
0060    pluginDesc.addNode(edm::PluginDescription<HelperFactory>("type") );
0061  
0062    ParameterSetDescription desc;
0063    desc.add<ParameterSetDescription>("pluginDescription", pluginDesc);
0064  
0065    oDesc.addDefault(desc);
0066  }
0067  \endcode
0068  
0069  4) Factory registration
0070  Use \c EDM_REGISTER_VALIDATED_PLUGINFACTORY rather than
0071  \c EDM_REGISTER_PLUGINFACTORY. This new macro can be found in
0072  FWCore/ParameterSet/interface/ValidatedPluginFactoryMacros.h
0073  
0074  5) Plugin registration
0075  Use \c DEFINE_EDM_VALIDATED_PLUGIN rather than \c DEFINE_EDM_PLUGIN.
0076  This new macro can be found in FWCore/Framework/interface/ValidatedPluginMacros.h
0077  
0078  */
0079 //
0080 // Original Author:  Chris Jones
0081 //         Created:  Wed, 19 Sep 2018 19:23:27 GMT
0082 //
0083 
0084 // system include files
0085 #include "FWCore/ParameterSet/interface/ParameterDescriptionNode.h"
0086 #include "FWCore/ParameterSet/interface/PluginDescriptionAdaptorBase.h"
0087 #include "FWCore/PluginManager/interface/PluginFactory.h"
0088 #include "FWCore/PluginManager/interface/PluginManager.h"
0089 #include "FWCore/PluginManager/interface/standard.h"
0090 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0091 
0092 // user include files
0093 #include <string>
0094 
0095 // forward declarations
0096 namespace edm {
0097   template <typename T>
0098   class PluginDescription : public ParameterDescriptionNode {
0099   public:
0100     /**Constructor without a default for typeLabel
0101    @param[in] typeLabel the label for the std::string parameter which holds the plugin type to be loaded
0102    @param[in] typeLabelIsTracked 'true' if the parameter `typeLabel` is tracked, else should be false
0103    */
0104     PluginDescription(std::string typeLabel, bool typeLabelIsTracked)
0105         : typeLabel_{std::move(typeLabel)}, typeLabelIsTracked_{typeLabelIsTracked} {}
0106 
0107     /**Constructor with a default for typeLabel
0108    @param[in] typeLabel the label for the std::string parameter which holds the plugin type to be loaded
0109    @param[in] defaultType the default plugin type that should be loaded if no type is given
0110    @param[in] typeLabelIsTracked 'true' if the parameter `typeLabel` is tracked, else should be false
0111    */
0112     PluginDescription(std::string typeLabel, std::string defaultType, bool typeLabelIsTracked)
0113         : typeLabel_{std::move(typeLabel)},
0114           defaultType_{std::move(defaultType)},
0115           typeLabelIsTracked_{typeLabelIsTracked} {}
0116 
0117     // ---------- const member functions ---------------------
0118     ParameterDescriptionNode* clone() const final { return new PluginDescription<T>(*this); }
0119 
0120   protected:
0121     void checkAndGetLabelsAndTypes_(std::set<std::string>& usedLabels,
0122                                     std::set<ParameterTypes>& parameterTypes,
0123                                     std::set<ParameterTypes>& wildcardTypes) const final {}
0124 
0125     void validate_(ParameterSet& pset, std::set<std::string>& validatedLabels, bool optional) const final {
0126       loadDescription(findType(pset)).validate(pset);
0127       //all names are good
0128       auto n = pset.getParameterNames();
0129       validatedLabels.insert(n.begin(), n.end());
0130     }
0131 
0132     void writeCfi_(
0133         std::ostream& os, bool optional, bool& startWithComma, int indentation, bool& wroteSomething) const final {
0134       if (not defaultType_.empty()) {
0135         if (!edmplugin::PluginManager::isAvailable()) {
0136           auto conf = edmplugin::standard::config();
0137           conf.allowNoCache();
0138           edmplugin::PluginManager::configure(conf);
0139         }
0140         loadDescription(defaultType_).writeCfi(os, startWithComma, indentation);
0141         wroteSomething = true;
0142       }
0143     }
0144 
0145     bool hasNestedContent_() const final { return true; }
0146 
0147     void printNestedContent_(std::ostream& os, bool /*optional*/, DocFormatHelper& dfh) const final {
0148       int indentation = dfh.indentation();
0149 
0150       using CreatedType = PluginDescriptionAdaptorBase<typename T::CreatedType>;
0151       using Factory = edmplugin::PluginFactory<CreatedType*()>;
0152 
0153       {
0154         std::stringstream ss;
0155         ss << dfh.section() << "." << dfh.counter();
0156         std::string newSection = ss.str();
0157 
0158         printSpaces(os, indentation);
0159         os << "Section " << newSection << " " << Factory::get()->category() << " Plugins description:\n";
0160         if (!dfh.brief())
0161           os << "\n";
0162       }
0163 
0164       //loop over all possible plugins
0165       unsigned int pluginCount = 0;
0166       std::string previousName;
0167       for (auto const& info :
0168            edmplugin::PluginManager::get()->categoryToInfos().find(Factory::get()->category())->second) {
0169         // We only want to print the first instance of each plugin name
0170         if (previousName == info.name_) {
0171           continue;
0172         }
0173 
0174         std::stringstream ss;
0175         ss << dfh.section() << "." << dfh.counter();
0176         std::string newSection = ss.str();
0177         printSpaces(os, indentation);
0178         os << "Section " << newSection << "." << ++pluginCount << " " << info.name_ << " Plugin description:\n";
0179         if (!dfh.brief())
0180           os << "\n";
0181 
0182         DocFormatHelper new_dfh(dfh);
0183         new_dfh.init();
0184         new_dfh.setSection(newSection);
0185 
0186         loadDescription(info.name_).print(os, new_dfh);
0187 
0188         previousName = info.name_;
0189       }
0190     }
0191 
0192     bool exists_(ParameterSet const& pset) const final {
0193       return pset.existsAs<std::string>(typeLabel_, typeLabelIsTracked_);
0194     }
0195 
0196     bool partiallyExists_(ParameterSet const& pset) const final { return exists_(pset); }
0197 
0198     int howManyXORSubNodesExist_(ParameterSet const& pset) const final { return exists(pset) ? 1 : 0; }
0199 
0200   private:
0201     std::string findType(edm::ParameterSet const& iPSet) const {
0202       if (typeLabelIsTracked_) {
0203         if (iPSet.existsAs<std::string>(typeLabel_) || defaultType_.empty()) {
0204           return iPSet.getParameter<std::string>(typeLabel_);
0205         } else {
0206           return defaultType_;
0207         }
0208       }
0209       if (defaultType_.empty()) {
0210         return iPSet.getUntrackedParameter<std::string>(typeLabel_);
0211       }
0212       return iPSet.getUntrackedParameter<std::string>(typeLabel_, defaultType_);
0213     }
0214 
0215     ParameterSetDescription loadDescription(std::string const& iName) const {
0216       using CreatedType = PluginDescriptionAdaptorBase<typename T::CreatedType>;
0217       std::unique_ptr<CreatedType> a(edmplugin::PluginFactory<CreatedType*()>::get()->create(iName));
0218 
0219       ParameterSetDescription desc = a->description();
0220 
0221       //There is no way to check to see if a node already wants a label
0222       if (typeLabelIsTracked_) {
0223         if (defaultType_.empty()) {
0224           desc.add<std::string>(typeLabel_);
0225         } else {
0226           desc.add<std::string>(typeLabel_, defaultType_);
0227         }
0228       } else {
0229         if (defaultType_.empty()) {
0230           desc.addUntracked<std::string>(typeLabel_);
0231         } else {
0232           desc.addUntracked<std::string>(typeLabel_, defaultType_);
0233         }
0234       }
0235       return desc;
0236     }
0237 
0238     // ---------- member data --------------------------------
0239     std::string typeLabel_;
0240     std::string defaultType_;
0241     bool typeLabelIsTracked_;
0242   };
0243 }  // namespace edm
0244 
0245 #endif