LCOV - code coverage report
Current view: top level - include/base - Registry.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33416 (b10b36) with base 9fbd27 Lines: 51 56 91.1 %
Date: 2026-07-23 16:15:30 Functions: 7364 11172 65.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include "InputParameters.h"
      13             : 
      14             : #include <string>
      15             : #include <vector>
      16             : #include <set>
      17             : #include <map>
      18             : #include <memory>
      19             : #include <optional>
      20             : 
      21             : #include "libmesh/utility.h"
      22             : 
      23             : #ifdef MOOSE_UNIT_TEST
      24             : #include <gtest/gtest.h>
      25             : #endif
      26             : 
      27             : #define combineNames1(X, Y) X##Y
      28             : #define combineNames(X, Y) combineNames1(X, Y)
      29             : 
      30             : /// This is provided as a convenience to globally set certain app names or labels used for
      31             : /// objects/actions as allowable.  While usually not needed, this macro can be useful for cases
      32             : /// when your app/module code may be compiled with other apps without your objects being
      33             : /// registered.  Calling this multiple times with the same argument is safe.
      34             : #define registerKnownLabel(X)                                                                      \
      35             :   [[maybe_unused]] static char combineNames(dummy_var_for_known_label, __COUNTER__) =              \
      36             :       Registry::addKnownLabel(X)
      37             : 
      38             : /// add an Action to the registry with the given app name/label as being associated with the given
      39             : /// task (quoted string).  classname is the (unquoted) c++ class.
      40             : #define registerMooseAction(app, classname, task)                                                  \
      41             :   [[maybe_unused]] static char combineNames(dummyvar_for_registering_action_##classname,           \
      42             :                                             __COUNTER__) =                                         \
      43             :       Registry::addAction<classname>({app, #classname, "", task, __FILE__, __LINE__, "", ""})
      44             : 
      45             : /// Add a MooseObject to the registry with the given app name/label.  classname is the (unquoted)
      46             : /// c++ class.  Each object/class should only be registered once.
      47             : #define registerMooseObject(app, classname)                                                        \
      48             :   [[maybe_unused]] static char combineNames(dummyvar_for_registering_obj_##classname,              \
      49             :                                             __COUNTER__) =                                         \
      50             :       Registry::add<classname>({app, #classname, "", "", __FILE__, __LINE__, "", ""})
      51             : 
      52             : #define registerADMooseObject(app, classname) registerMooseObject(app, classname)
      53             : 
      54             : /// Add a MooseObject to the registry with the given app name/label under an alternate alias/name
      55             : /// (quoted string) instead of the classname.
      56             : #define registerMooseObjectAliased(app, classname, alias)                                          \
      57             :   [[maybe_unused]] static char combineNames(dummyvar_for_registering_obj_##classname,              \
      58             :                                             __COUNTER__) =                                         \
      59             :       Registry::add<classname>({app, #classname, alias, "", __FILE__, __LINE__, "", ""})
      60             : 
      61             : /// Add a deprecated MooseObject to the registry with the given app name/label. time is the time
      62             : /// the object became/becomes deprecated in "mm/dd/yyyy HH:MM" format.
      63             : #define registerMooseObjectDeprecated(app, classname, time)                                        \
      64             :   [[maybe_unused]] static char combineNames(dummyvar_for_registering_obj_##classname,              \
      65             :                                             __COUNTER__) =                                         \
      66             :       Registry::add<classname>({app, #classname, "", "", __FILE__, __LINE__, time, ""})
      67             : 
      68             : #define registerADMooseObjectDeprecated(app, classname, time)                                      \
      69             :   registerMooseObjectDeprecated(app, classname, time)
      70             : 
      71             : /// add a deprecated MooseObject to the registry that has been replaced by another
      72             : /// object. time is the time the object became/becomes deprecated in "mm/dd/yyyy hh:mm" format.
      73             : #define registerMooseObjectReplaced(app, classname, time, replacement)                             \
      74             :   [[maybe_unused]] static char combineNames(dummyvar_for_registering_obj_##classname,              \
      75             :                                             __COUNTER__) =                                         \
      76             :       Registry::add<classname>({app, #classname, "", "", __FILE__, __LINE__, time, #replacement})
      77             : 
      78             : /// add a deprecated MooseObject orig_class to the registry that has been replaced by another
      79             : /// object new_class with the same API. time is the time the object became/becomes deprecated in
      80             : /// "mm/dd/yyyy hh:mm" format.
      81             : /// A call to registerMooseObject is still required for the new class
      82             : #define registerMooseObjectRenamed(app, orig_class, time, new_class)                               \
      83             :   [[maybe_unused]] static char combineNames(dummyvar_for_registering_obj_##orig_class,             \
      84             :                                             __COUNTER__) =                                         \
      85             :       Registry::add<new_class>(                                                                    \
      86             :           {app, #new_class, #orig_class, #orig_class, __FILE__, __LINE__, time, #new_class})
      87             : 
      88             : #define registerADMooseObjectRenamed(app, orig_class, time, new_class)                             \
      89             :   registerMooseObjectRenamed(app, orig_class, time, new_class)
      90             : 
      91             : /// Register a non-MooseApp data file path (folder name must be data)
      92             : #define registerNonAppDataFilePath(name, path) Registry::addDataFilePath(name, path, false)
      93             : /// Register a non-MooseApp data file path (folder name must be data) with extra information
      94             : #define registerNonAppDataFilePathWithInfo(name, path, info)                                       \
      95             :   Registry::addDataFilePath(name, path, false, info)
      96             : /// Register a data file path for an application. Uses the current file to register
      97             : /// ../../data as a path. The app name must be the APPLICATION_NAME used to build
      98             : /// the app (solid_mechanics instead of SolidMechanicsApp, for example)
      99             : #define registerAppDataFilePath(app) Registry::addAppDataFilePath(app, __FILE__)
     100             : /// Register a missing data file path (adds the data capability as missing)
     101             : #define registerMissingDataFilePath(name, info) Registry::addMissingDataFilePath(name, info)
     102             : /// Deprecated method; use registerAppDataFilePath instead
     103             : #define registerDataFilePath() Registry::addDeprecatedAppDataFilePath(__FILE__)
     104             : 
     105             : #define registerRepository(repo_name, repo_url) Registry::addRepository(repo_name, repo_url);
     106             : 
     107             : class Factory;
     108             : class ActionFactory;
     109             : class MooseObject;
     110             : class Action;
     111             : struct RegistryEntryBase;
     112             : 
     113             : /**
     114             :  * Holds details and meta-data info for a particular MooseObject or Action for use in the
     115             :  * use in the registry.
     116             :  */
     117             : struct RegistryEntryData
     118             : {
     119             :   /// label (usually app name - e.g. "YourAnimalApp") that the object or action is associated with.
     120             :   std::string _label;
     121             :   /// name of the c++ class for the object.
     122             :   std::string _classname;
     123             :   /// an alternate name to register the object to factories under.
     124             :   /// If unspecified, _classname is used.
     125             :   std::string _alias;
     126             :   /// name that the object will be registered to factories under.  If unspecified, _alias is used.
     127             :   std::string _name;
     128             :   /// file path for the c++ file the object or action was added to the registry in.
     129             :   std::string _file;
     130             :   /// line number in the c++ file the object or action was added to the registry on.
     131             :   int _line;
     132             :   /// time in "mm/dd/yyyy HH:MM" format that the object is/becomes deprecated, blank otherwise.
     133             :   std::string _deprecated_time;
     134             :   /// class name for an object that replaces this object if deprecated, blank otherwise.
     135             :   std::string _replaced_by;
     136             : };
     137             : 
     138             : struct RegistryEntryBase : public RegistryEntryData
     139             : {
     140   106164273 :   RegistryEntryBase(const RegistryEntryData & data) : RegistryEntryData(data) {}
     141           0 :   virtual ~RegistryEntryBase() {}
     142             :   /// proxy functions
     143             :   virtual std::unique_ptr<MooseObject> build(const InputParameters & parameters) = 0;
     144             :   virtual std::shared_ptr<MooseObject> buildShared(const InputParameters & parameters) = 0;
     145             :   virtual std::shared_ptr<Action> buildAction(const InputParameters & parameters) = 0;
     146             :   virtual InputParameters buildParameters() = 0;
     147             :   /// resolve the name from _classname, _alias, and _name
     148   323833819 :   std::string name() const
     149             :   {
     150   323833819 :     std::string name = _name;
     151   323833819 :     if (name.empty())
     152   313684047 :       name = _alias;
     153   323833819 :     if (name.empty())
     154   310428092 :       name = _classname;
     155   323833819 :     return name;
     156           0 :   }
     157             : };
     158             : 
     159             : template <typename T>
     160             : struct RegistryEntry : public RegistryEntryBase
     161             : {
     162             :   RegistryEntry(const RegistryEntryData & data);
     163             :   virtual std::unique_ptr<MooseObject> build(const InputParameters & parameters) override;
     164             :   virtual std::shared_ptr<MooseObject> buildShared(const InputParameters & parameters) override;
     165             :   virtual std::shared_ptr<Action> buildAction(const InputParameters & parameters) override;
     166             :   virtual InputParameters buildParameters() override;
     167             : };
     168             : 
     169             : /// The registry is used as a global singleton to collect information on all available MooseObject
     170             : /// and Action classes for use in a moose app/simulation.  It must be global because we want+need
     171             : /// to be able to register objects in global scope during static initialization time before other
     172             : /// parts of the moose app execution have started running.  This allows us to distribute
     173             : /// registration across all the files that define the actual classes being registered so we don't
     174             : /// have to have any central location with a bajillion includes that makes (especially incremental)
     175             : /// compiles slow. The registry collects the app, name, and other information for each objects and
     176             : /// makes it available to the moose object and action factories and others for general use.  All
     177             : /// public functions in this class modify and return data from the global singleton.
     178             : class Registry
     179             : {
     180             : public:
     181             :   /**
     182             :    * Get the global Registry singleton.
     183             :    */
     184             :   static Registry & getRegistry();
     185             : 
     186             :   /// Adds information on a MooseObject to the registry.  The _build_ptr, _build_action_ptr, and
     187             :   /// _params_ptr objects of the info object should all be nullptr - these are set automatically by
     188             :   /// the add function itself using the templated type T.
     189             :   template <typename T>
     190    93577948 :   static char add(const RegistryEntryData & base_info)
     191             :   {
     192    93577948 :     const auto info = std::make_shared<RegistryEntry<T>>(base_info);
     193    93577948 :     getRegistry()._per_label_objects[info->_label].push_back(info);
     194   280733844 :     getRegistry()._type_to_classname[typeid(T).name()] = info->name();
     195    93577948 :     return 0;
     196    93577948 :   }
     197             : 
     198             :   /// Adds information on an Action object to the registry.  The _build_ptr, _build_action_ptr, and
     199             :   /// _params_ptr objects of the info object should all be nullptr - these are set automatically by
     200             :   /// the addAction function itself using the templated type T.
     201             :   template <typename T>
     202    12586325 :   static char addAction(const RegistryEntryData & base_info)
     203             :   {
     204    12586325 :     const auto info = std::make_shared<RegistryEntry<T>>(base_info);
     205    12586325 :     getRegistry()._per_label_actions[info->_label].push_back(info);
     206    25172650 :     getRegistry()._type_to_classname[typeid(T).name()] = info->_classname;
     207    12586325 :     return 0;
     208    12586325 :   }
     209             : 
     210             :   template <typename T>
     211         294 :   static std::string getClassName()
     212             :   {
     213         294 :     return libmesh_map_find(getRegistry()._type_to_classname, typeid(T).name());
     214             :   }
     215             : 
     216             :   /// This registers all MooseObjects known to the registry that have the given label(s) with the
     217             :   /// factory f.
     218             :   static void registerObjectsTo(Factory & f, const std::set<std::string> & labels);
     219             : 
     220             :   /// This registers all Actions known to the registry that have the given label(s) with the
     221             :   /// factory f.
     222             :   static void registerActionsTo(ActionFactory & f, const std::set<std::string> & labels);
     223             : 
     224             :   /// addKnownLabel whitelists a label as valid for purposes of the checkLabels function.
     225             :   static char addKnownLabel(const std::string & label);
     226             : 
     227             :   /// register general search paths; "app" is whether or not the path is an app path
     228             :   static void addDataFilePath(const std::string & name,
     229             :                               const std::string & in_tree_path,
     230             :                               const bool app = true,
     231             :                               const std::optional<std::string> & info = {});
     232             :   /// register search paths for an application (path determined relative to app_path);
     233             :   /// app_path should be passed as __FILE__ from the application source file
     234             :   static void addAppDataFilePath(const std::string & app_name, const std::string & app_path);
     235             :   /// register a data file path as missing, along with info about how it can be added
     236             :   static void addMissingDataFilePath(const std::string & name, const std::string & info);
     237             :   /// deprecated method; use addAppDataFilePath instead
     238             :   static void addDeprecatedAppDataFilePath(const std::string & app_path);
     239             : 
     240             :   /// register a repository
     241             :   static void addRepository(const std::string & repo_name, const std::string & repo_url);
     242             : 
     243             :   /// Register a citation (the full BibTeX \p bibtex text, identified by \p key) tied to the app
     244             :   /// \p app_name; emitted by --citations when any object registered to that app is constructed. The
     245             :   /// framework registers its paper under "MooseApp", so apps composed of MooseApp inherit it.
     246             :   static void
     247             :   addAppCitation(const std::string & app_name, const std::string & key, const std::string & bibtex);
     248             : 
     249             :   /// Returns a per-label keyed map of all MooseObjects in the registry.
     250          42 :   static const std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> & allObjects()
     251             :   {
     252          42 :     return getRegistry()._per_label_objects;
     253             :   }
     254             :   /// Returns a per-label keyed map of all Actions in the registry.
     255          42 :   static const std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> & allActions()
     256             :   {
     257          42 :     return getRegistry()._per_label_actions;
     258             :   }
     259             : 
     260             :   static const RegistryEntryBase & objData(const std::string & name);
     261             : 
     262             :   /**
     263             :    * \returns true if an object with the given name is registered
     264             :    */
     265     2412095 :   static bool isRegisteredObj(const std::string & name)
     266             :   {
     267     2412095 :     return getRegistry()._name_to_entry.count(name);
     268             :   }
     269             : 
     270             :   /// Returns a map of all registered data file paths (name -> path)
     271       21700 :   static const std::map<std::string, std::string> & getDataFilePaths()
     272             :   {
     273       21700 :     return getRegistry()._data_file_paths;
     274             :   }
     275             :   /**
     276             :    * Gets a data path for the registered name.
     277             :    *
     278             :    * Finds either the installed path or the in-tree path.
     279             :    */
     280             :   static std::string getDataFilePath(const std::string & name);
     281             : 
     282             :   /// Returns the repository URL associated with \p repo_name
     283             :   static const std::string & getRepositoryURL(const std::string & repo_name);
     284             :   /**
     285             :    * Returns a map of all registered repositories
     286             :    */
     287          34 :   static const std::map<std::string, std::string> & getRepos() { return getRegistry()._repos; }
     288             : 
     289             :   /// Returns the registered citations, keyed by app/module name and then by BibTeX key
     290             :   /// (app/module name -> (BibTeX key -> BibTeX entry text))
     291           2 :   static const std::map<std::string, std::map<std::string, std::string>> & getCitations()
     292             :   {
     293           2 :     return getRegistry()._app_citations;
     294             :   }
     295             :   /// Returns the citations (BibTeX key -> BibTeX entry text) tied to \p app_name, or an empty map
     296             :   /// if no citations are registered for it. Most apps/modules register none, so the empty result
     297             :   /// is a normal case: callers iterate over all constructed objects' labels and gather whatever
     298             :   /// citations exist.
     299             :   static const std::map<std::string, std::string> & getCitations(const std::string & app_name);
     300             : 
     301             :   /// returns the name() for a registered class
     302             :   template <typename T>
     303             :   static std::string getRegisteredName();
     304             : 
     305             :   ///@{ Don't allow creation through copy/move construction or assignment
     306             :   Registry(Registry const &) = delete;
     307             :   Registry & operator=(Registry const &) = delete;
     308             : 
     309             :   Registry(Registry &&) = delete;
     310             :   Registry & operator=(Registry &&) = delete;
     311             :   ///@}
     312             : 
     313             : private:
     314             : #ifdef MOOSE_UNIT_TEST
     315             :   /// Friends for unit testing
     316             :   ///@{
     317             :   friend class RegistryTest;
     318             :   friend class DataFileUtilsTest;
     319             :   FRIEND_TEST(RegistryTest, determineFilePath);
     320             :   FRIEND_TEST(RegistryTest, determineFilePathFailed);
     321             :   FRIEND_TEST(RegistryTest, appNameFromAppPath);
     322             :   FRIEND_TEST(RegistryTest, appNameFromAppPathFailed);
     323             :   FRIEND_TEST(RegistryTest, addDataFilePathCapability);
     324             :   ///@}
     325             : #endif
     326             : 
     327       55280 :   Registry() {};
     328             : 
     329             :   /**
     330             :    * Manually set the data file paths.
     331             :    *
     332             :    * Used in unit testing.
     333             :    */
     334         128 :   static void setDataFilePaths(const std::map<std::string, std::string> & data_file_paths)
     335             :   {
     336         128 :     getRegistry()._data_file_paths = data_file_paths;
     337         128 :   }
     338             :   /**
     339             :    * Manually set the repos.
     340             :    *
     341             :    * Used in unit testing
     342             :    */
     343          68 :   static void setRepos(const std::map<std::string, std::string> & repos)
     344             :   {
     345          68 :     getRegistry()._repos = repos;
     346          68 :   }
     347             : 
     348             :   /// Internal helper for determing a root data file path (in-tree vs installed)
     349             :   static std::string determineDataFilePath(const std::string & name,
     350             :                                            const std::string & in_tree_path);
     351             : 
     352             :   /// Internal helper for getting an application name from its path, for example:
     353             :   /// /path/to/FooBarBazApp.C -> foo_bar_baz, for use in addDeprecatedAppDataFilePath
     354             :   static std::string appNameFromAppPath(const std::string & app_path);
     355             : 
     356             :   /// Check a data file path for valid characters
     357             :   static void checkDataFilePathName(const std::string & name);
     358             : 
     359             :   /// Add a data file path capability
     360             :   static void addDataFilePathCapability(const std::string & name,
     361             :                                         const std::optional<std::string> & path = {},
     362             :                                         const std::optional<std::string> & extra_info = {});
     363             : 
     364             :   std::map<std::string, std::shared_ptr<RegistryEntryBase>> _name_to_entry;
     365             :   std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> _per_label_objects;
     366             :   std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> _per_label_actions;
     367             :   std::set<std::string> _known_labels;
     368             :   /// Data file registry; name -> in-tree path
     369             :   std::map<std::string, std::string> _data_file_paths;
     370             :   /// Repository name -> repository URL; used for mooseDocumentedError
     371             :   std::map<std::string, std::string> _repos;
     372             :   std::map<std::string, std::string> _type_to_classname;
     373             :   /// App/module name -> (citation key -> BibTeX entry text) for that app
     374             :   std::map<std::string, std::map<std::string, std::string>> _app_citations;
     375             : };
     376             : 
     377             : template <typename T>
     378             : std::string
     379             : Registry::getRegisteredName()
     380             : {
     381             :   mooseDeprecated("Use Registry::getClassName() instead.");
     382             :   return getClassName<T>();
     383             : }
     384             : 
     385             : template <typename T>
     386   106164273 : RegistryEntry<T>::RegistryEntry(const RegistryEntryData & data) : RegistryEntryBase(data)
     387             : {
     388             :   static_assert(std::is_base_of_v<MooseObject, T> || std::is_base_of_v<Action, T>,
     389             :                 "Not derived from MooseObject or Action");
     390   106164273 : }
     391             : 
     392             : template <typename T>
     393             : std::unique_ptr<MooseObject>
     394        1987 : RegistryEntry<T>::build(const InputParameters & parameters)
     395             : {
     396             :   if constexpr (std::is_base_of_v<MooseObject, T>)
     397        1987 :     return std::make_unique<T>(parameters);
     398           0 :   mooseError(MooseUtils::prettyCppType<T>(), " to be built is not a MooseObject.");
     399             : }
     400             : template <typename T>
     401             : std::shared_ptr<MooseObject>
     402     2123648 : RegistryEntry<T>::buildShared(const InputParameters & parameters)
     403             : {
     404             :   if constexpr (std::is_base_of_v<MooseObject, T>)
     405     2123648 :     return std::make_shared<T>(parameters);
     406           0 :   mooseError(MooseUtils::prettyCppType<T>(), " to be built is not a MooseObject.");
     407             : }
     408             : 
     409             : template <typename T>
     410             : std::shared_ptr<Action>
     411     3418125 : RegistryEntry<T>::buildAction(const InputParameters & parameters)
     412             : {
     413             :   if constexpr (!std::is_base_of_v<Action, T>)
     414           0 :     mooseError("The action to be built is not derived from Action.");
     415             :   else
     416     3418125 :     return std::make_shared<T>(parameters);
     417             : }
     418             : 
     419             : template <typename T>
     420             : InputParameters
     421    12943964 : RegistryEntry<T>::buildParameters()
     422             : {
     423    12943964 :   auto params = T::validParams();
     424    12943964 :   return params;
     425             : }

Generated by: LCOV version 1.14