LCOV - code coverage report
Current view: top level - src/base - Registry.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 89 95 93.7 %
Date: 2025-07-17 01:28:37 Functions: 12 13 92.3 %
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             : #include "InputParameters.h"
      11             : #include "Registry.h"
      12             : #include "Factory.h"
      13             : #include "ActionFactory.h"
      14             : #include "MooseUtils.h"
      15             : 
      16             : #include "libmesh/libmesh_common.h"
      17             : 
      18             : #include <memory>
      19             : #include <filesystem>
      20             : #include <regex>
      21             : 
      22             : Registry &
      23   176893313 : Registry::getRegistry()
      24             : {
      25             :   // We need a naked new here (_not_ a smart pointer or object instance) due to what seems like a
      26             :   // bug in clang's static object destruction when using dynamic library loading.
      27             :   static Registry * registry_singleton = nullptr;
      28   176893313 :   if (!registry_singleton)
      29       51208 :     registry_singleton = new Registry();
      30   176893313 :   return *registry_singleton;
      31             : }
      32             : 
      33             : void
      34      125519 : Registry::registerObjectsTo(Factory & f, const std::set<std::string> & labels)
      35             : {
      36      125519 :   auto & r = getRegistry();
      37             : 
      38      251038 :   for (const auto & label : labels)
      39             :   {
      40      125519 :     r._known_labels.insert(label);
      41      125519 :     if (r._per_label_objects.count(label) == 0)
      42           5 :       continue;
      43             : 
      44    93713890 :     for (const auto & obj : r._per_label_objects[label])
      45             :     {
      46    93588376 :       const auto name = obj->name();
      47    93588376 :       r._name_to_entry[name] = obj;
      48             : 
      49    93588376 :       f.reg(obj);
      50    93588376 :       if (!obj->_alias.empty())
      51     4204397 :         f.associateNameToClass(name, obj->_classname);
      52    93588376 :     }
      53             :   }
      54      125519 : }
      55             : 
      56             : const RegistryEntryBase &
      57           0 : Registry::objData(const std::string & name)
      58             : {
      59           0 :   auto & r = getRegistry();
      60             : 
      61           0 :   if (const auto it = r._name_to_entry.find(name); it != r._name_to_entry.end())
      62           0 :     return *it->second;
      63             :   else
      64           0 :     mooseError("Object ", name, " is not registered yet");
      65             : }
      66             : 
      67             : void
      68      125330 : Registry::registerActionsTo(ActionFactory & f, const std::set<std::string> & labels)
      69             : {
      70      125330 :   auto & r = getRegistry();
      71             : 
      72      250660 :   for (const auto & label : labels)
      73             :   {
      74      125330 :     r._known_labels.insert(label);
      75      125330 :     if (r._per_label_actions.count(label) == 0)
      76          17 :       continue;
      77             : 
      78    13222837 :     for (const auto & obj : r._per_label_actions[label])
      79    13097524 :       f.reg(obj);
      80             :   }
      81      125330 : }
      82             : 
      83             : char
      84       62823 : Registry::addKnownLabel(const std::string & label)
      85             : {
      86       62823 :   getRegistry()._known_labels.insert(label);
      87       62823 :   return 0;
      88             : }
      89             : 
      90             : void
      91       62786 : Registry::addDataFilePath(const std::string & name, const std::string & in_tree_path)
      92             : {
      93       62786 :   if (!std::regex_search(name, std::regex("\\w+")))
      94           1 :     mooseError("Unallowed characters in '", name, "'");
      95             : 
      96             :   // Enforce that the folder is called "data", because we rely on the installed path
      97             :   // to be within PREFIX/share/<name>/data (see determineDataFilePath())
      98       62785 :   const std::string folder = std::filesystem::path(in_tree_path).filename().c_str();
      99       62785 :   if (folder != "data")
     100           1 :     mooseError("While registering data file path '",
     101             :                in_tree_path,
     102             :                "' for '",
     103             :                name,
     104             :                "': The folder must be named 'data' and it is named '",
     105             :                folder,
     106             :                "'");
     107             : 
     108             :   // Find either the installed or in-tree path
     109       62784 :   const auto path = determineDataFilePath(name, in_tree_path);
     110             : 
     111       62784 :   auto & dfp = getRegistry()._data_file_paths;
     112       62784 :   const auto it = dfp.find(name);
     113             :   // Not registered yet
     114       62784 :   if (it == dfp.end())
     115       51201 :     dfp.emplace(name, path);
     116             :   // Registered, but with a different value
     117       11583 :   else if (it->second != path)
     118           1 :     mooseError("While registering data file path '",
     119             :                path,
     120             :                "' for '",
     121             :                name,
     122             :                "': the path '",
     123           1 :                it->second,
     124             :                "' is already registered");
     125       62786 : }
     126             : 
     127             : void
     128       62758 : Registry::addAppDataFilePath(const std::string & app_name, const std::string & app_path)
     129             : {
     130             :   // split the *App.C filename from its containing directory
     131       62758 :   const auto dir = MooseUtils::splitFileName(app_path).first;
     132             :   // This works for both build/unity_src/ and src/base/ as the *App.C file location,
     133             :   // in case __FILE__ doesn't get overriden in unity build
     134       62758 :   addDataFilePath(app_name, MooseUtils::pathjoin(dir, "../../data"));
     135       62758 : }
     136             : 
     137             : void
     138           1 : Registry::addDeprecatedAppDataFilePath(const std::string & app_path)
     139             : {
     140           1 :   const auto app_name = appNameFromAppPath(app_path);
     141           1 :   mooseDeprecated("In ",
     142             :                   app_path,
     143             :                   ":\nregisterDataFilePath() is deprecated. Use registerAppDataFilePath(\"",
     144             :                   app_name,
     145             :                   "\") instead.");
     146           1 :   addAppDataFilePath(app_name, app_path);
     147           1 : }
     148             : 
     149             : std::string
     150           4 : Registry::getDataFilePath(const std::string & name)
     151             : {
     152           4 :   const auto & dfps = getRegistry()._data_file_paths;
     153           4 :   const auto it = dfps.find(name);
     154           4 :   if (it == dfps.end())
     155           1 :     mooseError("Registry::getDataFilePath(): A data file path for '", name, "' is not registered");
     156           6 :   return it->second;
     157             : }
     158             : 
     159             : void
     160       62756 : Registry::addRepository(const std::string & repo_name, const std::string & repo_url)
     161             : {
     162       62756 :   auto & repos = getRegistry()._repos;
     163       62756 :   const auto [it, inserted] = repos.emplace(repo_name, repo_url);
     164       62756 :   if (!inserted && it->second != repo_url)
     165           1 :     mooseError("Registry::registerRepository(): The repository '",
     166             :                repo_name,
     167             :                "' is already registered with a different URL '",
     168           1 :                it->second,
     169             :                "'.");
     170       62755 : }
     171             : 
     172             : const std::string &
     173           8 : Registry::getRepositoryURL(const std::string & repo_name)
     174             : {
     175           8 :   const auto & repos = getRegistry()._repos;
     176           8 :   if (const auto it = repos.find(repo_name); it != repos.end())
     177           7 :     return it->second;
     178           1 :   mooseError("Registry::getRepositoryURL(): The repository '", repo_name, "' is not registered.");
     179             : }
     180             : 
     181             : std::string
     182       62786 : Registry::determineDataFilePath(const std::string & name, const std::string & in_tree_path)
     183             : {
     184             :   // TODO: Track whether or not the application is installed in a better way
     185             :   // than this, which will enable us to pick one or the other based on
     186             :   // the install state. This probably also won't work with dynamic loading, where
     187             :   // we can't necessarily get this information from the binary (as there could be
     188             :   // multiple binary paths)
     189             : 
     190             :   // Installed data
     191             :   const auto installed_path =
     192       62786 :       MooseUtils::pathjoin(Moose::getExecutablePath(), "..", "share", name, "data");
     193       62786 :   if (MooseUtils::checkFileReadable(installed_path, false, false, false))
     194           0 :     return MooseUtils::canonicalPath(installed_path);
     195             : 
     196             :   // In tree data
     197       62786 :   if (MooseUtils::checkFileReadable(in_tree_path, false, false, false))
     198       62785 :     return MooseUtils::canonicalPath(in_tree_path);
     199             : 
     200           1 :   mooseError("Failed to determine data file path for '",
     201             :              name,
     202             :              "'. Paths searched:\n\n  installed: ",
     203             :              installed_path,
     204             :              "\n  in-tree: ",
     205             :              in_tree_path);
     206       62786 : }
     207             : 
     208             : std::string
     209           3 : Registry::appNameFromAppPath(const std::string & app_path)
     210             : {
     211             :   // This is for deprecated use only. It assumes that the application name
     212             :   // (binary name) in the build follows our normal naming of FooBarApp -> foo_bar.
     213             :   // We need to convert the application source file to the above, for example:
     214             :   //   /path/to/FooBarBazApp.C -> foo_bar_baz
     215             :   // Ideally, we would instead have the user specify this manually so that
     216             :   // there is no ambiguity.
     217           3 :   std::smatch match;
     218           3 :   if (std::regex_search(app_path, match, std::regex("\\/([a-zA-Z0-9_]+)App\\.C$")))
     219             :   {
     220           2 :     std::string name = match[1];                                        // FooBarBaz
     221           2 :     name = std::regex_replace(name, std::regex("(?!^)([A-Z])"), "_$1"); // Foo_Bar_Baz
     222           2 :     name = MooseUtils::toLower(name);                                   // foo_bar_baz
     223           4 :     return name;
     224           2 :   }
     225             : 
     226           1 :   mooseError(
     227             :       "Registry::appNameFromAppPath(): Failed to parse application name from '", app_path, "'");
     228           3 : }

Generated by: LCOV version 1.14