LCOV - code coverage report
Current view: top level - include/base - Registry.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 46 50 92.0 %
Date: 2025-07-17 01:28:37 Functions: 6350 8055 78.8 %
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    87113875 :   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<Action> buildAction(const InputParameters & parameters) = 0;
     130             :   virtual InputParameters buildParameters() = 0;
     131             :   /// resolve the name from _classname, _alias, and _name
     132   263911231 :   std::string name() const
     133             :   {
     134   263911231 :     std::string name = _name;
     135   263911231 :     if (name.empty())
     136   254888333 :       name = _alias;
     137   263911231 :     if (name.empty())
     138   252057544 :       name = _classname;
     139   263911231 :     return name;
     140           0 :   }
     141             : };
     142             : 
     143             : template <typename T>
     144             : struct RegistryEntry : public RegistryEntryBase
     145             : {
     146    87113875 :   RegistryEntry(const RegistryEntryData & data) : RegistryEntryBase(data) {}
     147             :   virtual std::unique_ptr<MooseObject> build(const InputParameters & parameters) override;
     148             :   virtual std::shared_ptr<Action> buildAction(const InputParameters & parameters) override;
     149             :   virtual InputParameters buildParameters() override;
     150             : };
     151             : 
     152             : /// The registry is used as a global singleton to collect information on all available MooseObject
     153             : /// and Action classes for use in a moose app/simulation.  It must be global because we want+need
     154             : /// to be able to register objects in global scope during static initialization time before other
     155             : /// parts of the moose app execution have started running.  This allows us to distribute
     156             : /// registration across all the files that define the actual classes being registered so we don't
     157             : /// have to have any central location with a bajillion includes that makes (especially incremental)
     158             : /// compiles slow. The registry collects the app, name, and other information for each objects and
     159             : /// makes it available to the moose object and action factories and others for general use.  All
     160             : /// public functions in this class modify and return data from the global singleton.
     161             : class Registry
     162             : {
     163             : public:
     164             :   /**
     165             :    * Get the global Registry singleton.
     166             :    */
     167             :   static Registry & getRegistry();
     168             : 
     169             :   /// Adds information on a MooseObject to the registry.  The _build_ptr, _build_action_ptr, and
     170             :   /// _params_ptr objects of the info object should all be nullptr - these are set automatically by
     171             :   /// the add function itself using the templated type T.
     172             :   template <typename T>
     173    76424073 :   static char add(const RegistryEntryData & base_info)
     174             :   {
     175    76424073 :     const auto info = std::make_shared<RegistryEntry<T>>(base_info);
     176    76424073 :     getRegistry()._per_label_objects[info->_label].push_back(info);
     177    76424073 :     getRegistry()._type_to_classname[typeid(T).name()] = info->name();
     178    76424073 :     return 0;
     179    76424073 :   }
     180             : 
     181             :   /// Adds information on an Action object to the registry.  The _build_ptr, _build_action_ptr, and
     182             :   /// _params_ptr objects of the info object should all be nullptr - these are set automatically by
     183             :   /// the addAction function itself using the templated type T.
     184             :   template <typename T>
     185    10689802 :   static char addAction(const RegistryEntryData & base_info)
     186             :   {
     187    10689802 :     const auto info = std::make_shared<RegistryEntry<T>>(base_info);
     188    10689802 :     getRegistry()._per_label_actions[info->_label].push_back(info);
     189    10689802 :     getRegistry()._type_to_classname[typeid(T).name()] = info->_classname;
     190    10689802 :     return 0;
     191    10689802 :   }
     192             : 
     193             :   template <typename T>
     194         291 :   static std::string getClassName()
     195             :   {
     196         582 :     return libmesh_map_find(getRegistry()._type_to_classname, typeid(T).name());
     197             :   }
     198             : 
     199             :   /// This registers all MooseObjects known to the registry that have the given label(s) with the
     200             :   /// factory f.
     201             :   static void registerObjectsTo(Factory & f, const std::set<std::string> & labels);
     202             : 
     203             :   /// This registers all Actions known to the registry that have the given label(s) with the
     204             :   /// factory f.
     205             :   static void registerActionsTo(ActionFactory & f, const std::set<std::string> & labels);
     206             : 
     207             :   /// addKnownLabel whitelists a label as valid for purposes of the checkLabels function.
     208             :   static char addKnownLabel(const std::string & label);
     209             : 
     210             :   /// register general search paths (folder name must be data)
     211             :   static void addDataFilePath(const std::string & name, const std::string & in_tree_path);
     212             :   /// register search paths for an application (path determined relative to app_path);
     213             :   /// app_path should be passed as __FILE__ from the application source file
     214             :   static void addAppDataFilePath(const std::string & app_name, const std::string & app_path);
     215             :   /// deprecated method; use addAppDataFilePath instead
     216             :   static void addDeprecatedAppDataFilePath(const std::string & app_path);
     217             : 
     218             :   /// register a repository
     219             :   static void addRepository(const std::string & repo_name, const std::string & repo_url);
     220             : 
     221             :   /// Returns a per-label keyed map of all MooseObjects in the registry.
     222         203 :   static const std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> & allObjects()
     223             :   {
     224         203 :     return getRegistry()._per_label_objects;
     225             :   }
     226             :   /// Returns a per-label keyed map of all Actions in the registry.
     227         203 :   static const std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> & allActions()
     228             :   {
     229         203 :     return getRegistry()._per_label_actions;
     230             :   }
     231             : 
     232             :   static const RegistryEntryBase & objData(const std::string & name);
     233             : 
     234             :   /**
     235             :    * \returns true if an object with the given name is registered
     236             :    */
     237     2204807 :   static bool isRegisteredObj(const std::string & name)
     238             :   {
     239     2204807 :     return getRegistry()._name_to_entry.count(name);
     240             :   }
     241             : 
     242             :   /// Returns a map of all registered data file paths (name -> path)
     243         300 :   static const std::map<std::string, std::string> & getDataFilePaths()
     244             :   {
     245         300 :     return getRegistry()._data_file_paths;
     246             :   }
     247             :   /**
     248             :    * Gets a data path for the registered name.
     249             :    *
     250             :    * Finds either the installed path or the in-tree path.
     251             :    */
     252             :   static std::string getDataFilePath(const std::string & name);
     253             : 
     254             :   /// Returns the repository URL associated with \p repo_name
     255             :   static const std::string & getRepositoryURL(const std::string & repo_name);
     256             :   /**
     257             :    * Returns a map of all registered repositories
     258             :    */
     259          12 :   static const std::map<std::string, std::string> & getRepos() { return getRegistry()._repos; }
     260             : 
     261             :   /// returns the name() for a registered class
     262             :   template <typename T>
     263             :   static std::string getRegisteredName();
     264             : 
     265             :   ///@{ Don't allow creation through copy/move construction or assignment
     266             :   Registry(Registry const &) = delete;
     267             :   Registry & operator=(Registry const &) = delete;
     268             : 
     269             :   Registry(Registry &&) = delete;
     270             :   Registry & operator=(Registry &&) = delete;
     271             :   ///@}
     272             : 
     273             : private:
     274             :   /// Friends for unit testing
     275             :   ///@{
     276             :   friend class RegistryTest;
     277             :   friend class DataFileUtilsTest;
     278             :   FRIEND_TEST(RegistryTest, determineFilePath);
     279             :   FRIEND_TEST(RegistryTest, determineFilePathFailed);
     280             :   FRIEND_TEST(RegistryTest, appNameFromAppPath);
     281             :   FRIEND_TEST(RegistryTest, appNameFromAppPathFailed);
     282             :   ///@}
     283             : 
     284       51208 :   Registry(){};
     285             : 
     286             :   /**
     287             :    * Manually set the data file paths.
     288             :    *
     289             :    * Used in unit testing.
     290             :    */
     291          46 :   static void setDataFilePaths(const std::map<std::string, std::string> & data_file_paths)
     292             :   {
     293          46 :     getRegistry()._data_file_paths = data_file_paths;
     294          46 :   }
     295             :   /**
     296             :    * Manually set the repos.
     297             :    *
     298             :    * Used in unit testing
     299             :    */
     300          24 :   static void setRepos(const std::map<std::string, std::string> & repos)
     301             :   {
     302          24 :     getRegistry()._repos = repos;
     303          24 :   }
     304             : 
     305             :   /// Internal helper for determing a root data file path (in-tree vs installed)
     306             :   static std::string determineDataFilePath(const std::string & name,
     307             :                                            const std::string & in_tree_path);
     308             : 
     309             :   /// Internal helper for getting an application name from its path, for example:
     310             :   /// /path/to/FooBarBazApp.C -> foo_bar_baz, for use in addDeprecatedAppDataFilePath
     311             :   static std::string appNameFromAppPath(const std::string & app_path);
     312             : 
     313             :   std::map<std::string, std::shared_ptr<RegistryEntryBase>> _name_to_entry;
     314             :   std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> _per_label_objects;
     315             :   std::map<std::string, std::vector<std::shared_ptr<RegistryEntryBase>>> _per_label_actions;
     316             :   std::set<std::string> _known_labels;
     317             :   /// Data file registry; name -> in-tree path
     318             :   std::map<std::string, std::string> _data_file_paths;
     319             :   /// Repository name -> repository URL; used for mooseDocumentedError
     320             :   std::map<std::string, std::string> _repos;
     321             :   std::map<std::string, std::string> _type_to_classname;
     322             : };
     323             : 
     324             : template <typename T>
     325             : std::string
     326             : Registry::getRegisteredName()
     327             : {
     328             :   mooseDeprecated("Use Registry::getClassName() instead.");
     329             :   return getClassName<T>();
     330             : }
     331             : 
     332             : template <typename T>
     333             : std::unique_ptr<MooseObject>
     334     1938809 : RegistryEntry<T>::build(const InputParameters & parameters)
     335             : {
     336             :   if constexpr (std::is_base_of_v<MooseObject, T>)
     337     1938809 :     return std::make_unique<T>(parameters);
     338           0 :   mooseError("The object to be built is not derived from MooseObject.");
     339             : }
     340             : 
     341             : template <typename T>
     342             : std::shared_ptr<Action>
     343     3008911 : RegistryEntry<T>::buildAction(const InputParameters & parameters)
     344             : {
     345             :   if constexpr (!std::is_base_of_v<Action, T>)
     346           0 :     mooseError("The action to be built is not derived from Action.");
     347             :   else
     348     3008911 :     return std::make_shared<T>(parameters);
     349             : }
     350             : 
     351             : template <typename T>
     352             : InputParameters
     353    28266171 : RegistryEntry<T>::buildParameters()
     354             : {
     355    28266171 :   auto params = T::validParams();
     356    28266171 :   return params;
     357             : }

Generated by: LCOV version 1.14