LCOV - code coverage report
Current view: top level - include/base - Registry.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #31706 (f8ed4a) with base bb0a08 Lines: 49 54 90.7 %
Date: 2025-11-03 17:23:24 Functions: 6742 10235 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             : 
      20             : #include "libmesh/utility.h"
      21             : 
      22             : #include <gtest/gtest.h>
      23             : 
      24             : #define combineNames1(X, Y) X##Y
      25             : #define combineNames(X, Y) combineNames1(X, Y)
      26             : 
      27             : /// This is provided as a convenience to globally set certain app names or labels used for
      28             : /// objects/actions as allowable.  While usually not needed, this macro can be useful for cases
      29             : /// when your app/module code may be compiled with other apps without your objects being
      30             : /// registered.  Calling this multiple times with the same argument is safe.
      31             : #define registerKnownLabel(X)                                                                      \
      32             :   static char combineNames(dummy_var_for_known_label, __COUNTER__) = Registry::addKnownLabel(X)
      33             : 
      34             : /// add an Action to the registry with the given app name/label as being associated with the given
      35             : /// task (quoted string).  classname is the (unquoted) c++ class.
      36             : #define registerMooseAction(app, classname, task)                                                  \
      37             :   static char combineNames(dummyvar_for_registering_action_##classname, __COUNTER__) =             \
      38             :       Registry::addAction<classname>({app, #classname, "", task, __FILE__, __LINE__, "", ""})
      39             : 
      40             : /// Add a MooseObject to the registry with the given app name/label.  classname is the (unquoted)
      41             : /// c++ class.  Each object/class should only be registered once.
      42             : #define registerMooseObject(app, classname)                                                        \
      43             :   static char combineNames(dummyvar_for_registering_obj_##classname, __COUNTER__) =                \
      44             :       Registry::add<classname>({app, #classname, "", "", __FILE__, __LINE__, "", ""})
      45             : 
      46             : #define registerADMooseObject(app, classname) registerMooseObject(app, classname)
      47             : 
      48             : /// Add a MooseObject to the registry with the given app name/label under an alternate alias/name
      49             : /// (quoted string) instead of the classname.
      50             : #define registerMooseObjectAliased(app, classname, alias)                                          \
      51             :   static char combineNames(dummyvar_for_registering_obj_##classname, __COUNTER__) =                \
      52             :       Registry::add<classname>({app, #classname, alias, "", __FILE__, __LINE__, "", ""})
      53             : 
      54             : /// Add a deprecated MooseObject to the registry with the given app name/label. time is the time
      55             : /// the object became/becomes deprecated in "mm/dd/yyyy HH:MM" format.
      56             : #define registerMooseObjectDeprecated(app, classname, time)                                        \
      57             :   static char combineNames(dummyvar_for_registering_obj_##classname, __COUNTER__) =                \
      58             :       Registry::add<classname>({app, #classname, "", "", __FILE__, __LINE__, time, ""})
      59             : 
      60             : #define registerADMooseObjectDeprecated(app, classname, time)                                      \
      61             :   registerMooseObjectDeprecated(app, classname, time)
      62             : 
      63             : /// add a deprecated MooseObject to the registry that has been replaced by another
      64             : /// object. time is the time the object became/becomes deprecated in "mm/dd/yyyy hh:mm" format.
      65             : #define registerMooseObjectReplaced(app, classname, time, replacement)                             \
      66             :   static char combineNames(dummyvar_for_registering_obj_##classname, __COUNTER__) =                \
      67             :       Registry::add<classname>({app, #classname, "", "", __FILE__, __LINE__, time, #replacement})
      68             : 
      69             : /// add a deprecated MooseObject orig_class to the registry that has been replaced by another
      70             : /// object new_class with the same API. time is the time the object became/becomes deprecated in
      71             : /// "mm/dd/yyyy hh:mm" format.
      72             : /// A call to registerMooseObject is still required for the new class
      73             : #define registerMooseObjectRenamed(app, orig_class, time, new_class)                               \
      74             :   static char combineNames(dummyvar_for_registering_obj_##orig_class, __COUNTER__) =               \
      75             :       Registry::add<new_class>(                                                                    \
      76             :           {app, #new_class, #orig_class, #orig_class, __FILE__, __LINE__, time, #new_class})
      77             : 
      78             : #define registerADMooseObjectRenamed(app, orig_class, time, new_class)                             \
      79             :   registerMooseObjectRenamed(app, orig_class, time, new_class)
      80             : 
      81             : /// Register a non-MooseApp data file path (folder name must be data)
      82             : #define registerNonAppDataFilePath(name, path) Registry::addDataFilePath(name, path)
      83             : /// Register a data file path for an application. Uses the current file to register
      84             : /// ../../data as a path. The app name must be the APPLICATION_NAME used to build
      85             : /// the app (solid_mechanics instead of SolidMechanicsApp, for example)
      86             : #define registerAppDataFilePath(app) Registry::addAppDataFilePath(app, __FILE__)
      87             : /// Deprecated method; use registerAppDataFilePath instead
      88             : #define registerDataFilePath() Registry::addDeprecatedAppDataFilePath(__FILE__)
      89             : 
      90             : #define registerRepository(repo_name, repo_url) Registry::addRepository(repo_name, repo_url);
      91             : 
      92             : class Factory;
      93             : class ActionFactory;
      94             : class MooseObject;
      95             : class Action;
      96             : struct RegistryEntryBase;
      97             : 
      98             : /**
      99             :  * Holds details and meta-data info for a particular MooseObject or Action for use in the
     100             :  * use in the registry.
     101             :  */
     102             : struct RegistryEntryData
     103             : {
     104             :   /// label (usually app name - e.g. "YourAnimalApp") that the object or action is associated with.
     105             :   std::string _label;
     106             :   /// name of the c++ class for the object.
     107             :   std::string _classname;
     108             :   /// an alternate name to register the object to factories under.
     109             :   /// If unspecified, _classname is used.
     110             :   std::string _alias;
     111             :   /// name that the object will be registered to factories under.  If unspecified, _alias is used.
     112             :   std::string _name;
     113             :   /// file path for the c++ file the object or action was added to the registry in.
     114             :   std::string _file;
     115             :   /// line number in the c++ file the object or action was added to the registry on.
     116             :   int _line;
     117             :   /// time in "mm/dd/yyyy HH:MM" format that the object is/becomes deprecated, blank otherwise.
     118             :   std::string _deprecated_time;
     119             :   /// class name for an object that replaces this object if deprecated, blank otherwise.
     120             :   std::string _replaced_by;
     121             : };
     122             : 
     123             : struct RegistryEntryBase : public RegistryEntryData
     124             : {
     125   101949534 :   RegistryEntryBase(const RegistryEntryData & data) : RegistryEntryData(data) {}
     126           0 :   virtual ~RegistryEntryBase() {}
     127             :   /// proxy functions
     128             :   virtual std::unique_ptr<MooseObject> build(const InputParameters & parameters) = 0;
     129             :   virtual std::shared_ptr<MooseObject> buildShared(const InputParameters & parameters) = 0;
     130             :   virtual std::shared_ptr<Action> buildAction(const InputParameters & parameters) = 0;
     131             :   virtual InputParameters buildParameters() = 0;
     132             :   /// resolve the name from _classname, _alias, and _name
     133   308744767 :   std::string name() const
     134             :   {
     135   308744767 :     std::string name = _name;
     136   308744767 :     if (name.empty())
     137   298472849 :       name = _alias;
     138   308744767 :     if (name.empty())
     139   294984375 :       name = _classname;
     140   308744767 :     return name;
     141           0 :   }
     142             : };
     143             : 
     144             : template <typename T>
     145             : struct RegistryEntry : public RegistryEntryBase
     146             : {
     147             :   RegistryEntry(const RegistryEntryData & data);
     148             :   virtual std::unique_ptr<MooseObject> build(const InputParameters & parameters) override;
     149             :   virtual std::shared_ptr<MooseObject> buildShared(const InputParameters & parameters) override;
     150             :   virtual std::shared_ptr<Action> buildAction(const InputParameters & parameters) override;
     151             :   virtual InputParameters buildParameters() override;
     152             : };
     153             : 
     154             : /// The registry is used as a global singleton to collect information on all available MooseObject
     155             : /// and Action classes for use in a moose app/simulation.  It must be global because we want+need
     156             : /// to be able to register objects in global scope during static initialization time before other
     157             : /// parts of the moose app execution have started running.  This allows us to distribute
     158             : /// registration across all the files that define the actual classes being registered so we don't
     159             : /// have to have any central location with a bajillion includes that makes (especially incremental)
     160             : /// compiles slow. The registry collects the app, name, and other information for each objects and
     161             : /// makes it available to the moose object and action factories and others for general use.  All
     162             : /// public functions in this class modify and return data from the global singleton.
     163             : class Registry
     164             : {
     165             : public:
     166             :   /**
     167             :    * Get the global Registry singleton.
     168             :    */
     169             :   static Registry & getRegistry();
     170             : 
     171             :   /// Adds information on a MooseObject to the registry.  The _build_ptr, _build_action_ptr, and
     172             :   /// _params_ptr objects of the info object should all be nullptr - these are set automatically by
     173             :   /// the add function itself using the templated type T.
     174             :   template <typename T>
     175    89535818 :   static char add(const RegistryEntryData & base_info)
     176             :   {
     177    89535818 :     const auto info = std::make_shared<RegistryEntry<T>>(base_info);
     178    89535818 :     getRegistry()._per_label_objects[info->_label].push_back(info);
     179   268607454 :     getRegistry()._type_to_classname[typeid(T).name()] = info->name();
     180    89535818 :     return 0;
     181    89535818 :   }
     182             : 
     183             :   /// Adds information on an Action object to the registry.  The _build_ptr, _build_action_ptr, and
     184             :   /// _params_ptr objects of the info object should all be nullptr - these are set automatically by
     185             :   /// the addAction function itself using the templated type T.
     186             :   template <typename T>
     187    12413739 :   static char addAction(const RegistryEntryData & base_info)
     188             :   {
     189    12413739 :     const auto info = std::make_shared<RegistryEntry<T>>(base_info);
     190    12413739 :     getRegistry()._per_label_actions[info->_label].push_back(info);
     191    24827478 :     getRegistry()._type_to_classname[typeid(T).name()] = info->_classname;
     192    12413739 :     return 0;
     193    12413739 :   }
     194             : 
     195             :   template <typename T>
     196         318 :   static std::string getClassName()
     197             :   {
     198         318 :     return libmesh_map_find(getRegistry()._type_to_classname, typeid(T).name());
     199             :   }
     200             : 
     201             :   /// This registers all MooseObjects known to the registry that have the given label(s) with the
     202             :   /// factory f.
     203             :   static void registerObjectsTo(Factory & f, const std::set<std::string> & labels);
     204             : 
     205             :   /// This registers all Actions known to the registry that have the given label(s) with the
     206             :   /// factory f.
     207             :   static void registerActionsTo(ActionFactory & f, const std::set<std::string> & labels);
     208             : 
     209             :   /// addKnownLabel whitelists a label as valid for purposes of the checkLabels function.
     210             :   static char addKnownLabel(const std::string & label);
     211             : 
     212             :   /// register general search paths (folder name must be data)
     213             :   static void addDataFilePath(const std::string & name, const std::string & in_tree_path);
     214             :   /// register search paths for an application (path determined relative to app_path);
     215             :   /// app_path should be passed as __FILE__ from the application source file
     216             :   static void addAppDataFilePath(const std::string & app_name, const std::string & app_path);
     217             :   /// deprecated method; use addAppDataFilePath instead
     218             :   static void addDeprecatedAppDataFilePath(const std::string & app_path);
     219             : 
     220             :   /// register a repository
     221             :   static void addRepository(const std::string & repo_name, const std::string & repo_url);
     222             : 
     223             :   /// Returns a per-label keyed map of all MooseObjects in the registry.
     224         203 :   static const std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> & allObjects()
     225             :   {
     226         203 :     return getRegistry()._per_label_objects;
     227             :   }
     228             :   /// Returns a per-label keyed map of all Actions in the registry.
     229         203 :   static const std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> & allActions()
     230             :   {
     231         203 :     return getRegistry()._per_label_actions;
     232             :   }
     233             : 
     234             :   static const RegistryEntryBase & objData(const std::string & name);
     235             : 
     236             :   /**
     237             :    * \returns true if an object with the given name is registered
     238             :    */
     239     2487908 :   static bool isRegisteredObj(const std::string & name)
     240             :   {
     241     2487908 :     return getRegistry()._name_to_entry.count(name);
     242             :   }
     243             : 
     244             :   /// Returns a map of all registered data file paths (name -> path)
     245         318 :   static const std::map<std::string, std::string> & getDataFilePaths()
     246             :   {
     247         318 :     return getRegistry()._data_file_paths;
     248             :   }
     249             :   /**
     250             :    * Gets a data path for the registered name.
     251             :    *
     252             :    * Finds either the installed path or the in-tree path.
     253             :    */
     254             :   static std::string getDataFilePath(const std::string & name);
     255             : 
     256             :   /// Returns the repository URL associated with \p repo_name
     257             :   static const std::string & getRepositoryURL(const std::string & repo_name);
     258             :   /**
     259             :    * Returns a map of all registered repositories
     260             :    */
     261          24 :   static const std::map<std::string, std::string> & getRepos() { return getRegistry()._repos; }
     262             : 
     263             :   /// returns the name() for a registered class
     264             :   template <typename T>
     265             :   static std::string getRegisteredName();
     266             : 
     267             :   ///@{ Don't allow creation through copy/move construction or assignment
     268             :   Registry(Registry const &) = delete;
     269             :   Registry & operator=(Registry const &) = delete;
     270             : 
     271             :   Registry(Registry &&) = delete;
     272             :   Registry & operator=(Registry &&) = delete;
     273             :   ///@}
     274             : 
     275             : private:
     276             :   /// Friends for unit testing
     277             :   ///@{
     278             :   friend class RegistryTest;
     279             :   friend class DataFileUtilsTest;
     280             :   FRIEND_TEST(RegistryTest, determineFilePath);
     281             :   FRIEND_TEST(RegistryTest, determineFilePathFailed);
     282             :   FRIEND_TEST(RegistryTest, appNameFromAppPath);
     283             :   FRIEND_TEST(RegistryTest, appNameFromAppPathFailed);
     284             :   ///@}
     285             : 
     286       57235 :   Registry() {};
     287             : 
     288             :   /**
     289             :    * Manually set the data file paths.
     290             :    *
     291             :    * Used in unit testing.
     292             :    */
     293          92 :   static void setDataFilePaths(const std::map<std::string, std::string> & data_file_paths)
     294             :   {
     295          92 :     getRegistry()._data_file_paths = data_file_paths;
     296          92 :   }
     297             :   /**
     298             :    * Manually set the repos.
     299             :    *
     300             :    * Used in unit testing
     301             :    */
     302          48 :   static void setRepos(const std::map<std::string, std::string> & repos)
     303             :   {
     304          48 :     getRegistry()._repos = repos;
     305          48 :   }
     306             : 
     307             :   /// Internal helper for determing a root data file path (in-tree vs installed)
     308             :   static std::string determineDataFilePath(const std::string & name,
     309             :                                            const std::string & in_tree_path);
     310             : 
     311             :   /// Internal helper for getting an application name from its path, for example:
     312             :   /// /path/to/FooBarBazApp.C -> foo_bar_baz, for use in addDeprecatedAppDataFilePath
     313             :   static std::string appNameFromAppPath(const std::string & app_path);
     314             : 
     315             :   std::map<std::string, std::shared_ptr<RegistryEntryBase>> _name_to_entry;
     316             :   std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> _per_label_objects;
     317             :   std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> _per_label_actions;
     318             :   std::set<std::string> _known_labels;
     319             :   /// Data file registry; name -> in-tree path
     320             :   std::map<std::string, std::string> _data_file_paths;
     321             :   /// Repository name -> repository URL; used for mooseDocumentedError
     322             :   std::map<std::string, std::string> _repos;
     323             :   std::map<std::string, std::string> _type_to_classname;
     324             : };
     325             : 
     326             : template <typename T>
     327             : std::string
     328             : Registry::getRegisteredName()
     329             : {
     330             :   mooseDeprecated("Use Registry::getClassName() instead.");
     331             :   return getClassName<T>();
     332             : }
     333             : 
     334             : template <typename T>
     335   101949557 : RegistryEntry<T>::RegistryEntry(const RegistryEntryData & data) : RegistryEntryBase(data)
     336             : {
     337             :   static_assert(std::is_base_of_v<MooseObject, T> || std::is_base_of_v<Action, T>,
     338             :                 "Not derived from MooseObject or Action");
     339   101949557 : }
     340             : 
     341             : template <typename T>
     342             : std::unique_ptr<MooseObject>
     343        1956 : RegistryEntry<T>::build(const InputParameters & parameters)
     344             : {
     345             :   if constexpr (std::is_base_of_v<MooseObject, T>)
     346        1956 :     return std::make_unique<T>(parameters);
     347           0 :   mooseError(MooseUtils::prettyCppType<T>(), " to be built is not a MooseObject.");
     348             : }
     349             : template <typename T>
     350             : std::shared_ptr<MooseObject>
     351     2189588 : RegistryEntry<T>::buildShared(const InputParameters & parameters)
     352             : {
     353             :   if constexpr (std::is_base_of_v<MooseObject, T>)
     354     2189588 :     return std::make_shared<T>(parameters);
     355           0 :   mooseError(MooseUtils::prettyCppType<T>(), " to be built is not a MooseObject.");
     356             : }
     357             : 
     358             : template <typename T>
     359             : std::shared_ptr<Action>
     360     3453228 : RegistryEntry<T>::buildAction(const InputParameters & parameters)
     361             : {
     362             :   if constexpr (!std::is_base_of_v<Action, T>)
     363           0 :     mooseError("The action to be built is not derived from Action.");
     364             :   else
     365     3453228 :     return std::make_shared<T>(parameters);
     366             : }
     367             : 
     368             : template <typename T>
     369             : InputParameters
     370    31154339 : RegistryEntry<T>::buildParameters()
     371             : {
     372    31154339 :   auto params = T::validParams();
     373    31154339 :   return params;
     374             : }

Generated by: LCOV version 1.14