LCOV - code coverage report
Current view: top level - src/base - Registry.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 99787a Lines: 89 95 93.7 %
Date: 2025-10-14 20:01:24 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   204530409 : 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   204530409 :   if (!registry_singleton)
      29       56987 :     registry_singleton = new Registry();
      30   204530409 :   return *registry_singleton;
      31             : }
      32             : 
      33             : void
      34      139621 : Registry::registerObjectsTo(Factory & f, const std::set<std::string> & labels)
      35             : {
      36      139621 :   auto & r = getRegistry();
      37             : 
      38      279242 :   for (const auto & label : labels)
      39             :   {
      40      139621 :     r._known_labels.insert(label);
      41      139621 :     if (r._per_label_objects.count(label) == 0)
      42          10 :       continue;
      43             : 
      44   108569266 :     for (const auto & obj : r._per_label_objects[label])
      45             :     {
      46   108429655 :       const auto name = obj->name();
      47   108429655 :       r._name_to_entry[name] = obj;
      48             : 
      49   108429655 :       f.reg(obj);
      50   108429655 :       if (!obj->_alias.empty())
      51     4862300 :         f.associateNameToClass(name, obj->_classname);
      52   108429655 :     }
      53             :   }
      54      139621 : }
      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      139233 : Registry::registerActionsTo(ActionFactory & f, const std::set<std::string> & labels)
      69             : {
      70      139233 :   auto & r = getRegistry();
      71             : 
      72      278466 :   for (const auto & label : labels)
      73             :   {
      74      139233 :     r._known_labels.insert(label);
      75      139233 :     if (r._per_label_actions.count(label) == 0)
      76          17 :       continue;
      77             : 
      78    14993971 :     for (const auto & obj : r._per_label_actions[label])
      79    14854755 :       f.reg(obj);
      80             :   }
      81      139233 : }
      82             : 
      83             : char
      84       69874 : Registry::addKnownLabel(const std::string & label)
      85             : {
      86       69874 :   getRegistry()._known_labels.insert(label);
      87       69874 :   return 0;
      88             : }
      89             : 
      90             : void
      91       69866 : Registry::addDataFilePath(const std::string & name, const std::string & in_tree_path)
      92             : {
      93       69866 :   if (!std::regex_search(name, std::regex("\\w+")))
      94           2 :     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       69864 :   const std::string folder = std::filesystem::path(in_tree_path).filename().c_str();
      99       69864 :   if (folder != "data")
     100           2 :     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       69862 :   const auto path = determineDataFilePath(name, in_tree_path);
     110             : 
     111       69862 :   auto & dfp = getRegistry()._data_file_paths;
     112       69862 :   const auto it = dfp.find(name);
     113             :   // Not registered yet
     114       69862 :   if (it == dfp.end())
     115       56993 :     dfp.emplace(name, path);
     116             :   // Registered, but with a different value
     117       12869 :   else if (it->second != path)
     118           2 :     mooseError("While registering data file path '",
     119             :                path,
     120             :                "' for '",
     121             :                name,
     122             :                "': the path '",
     123           2 :                it->second,
     124             :                "' is already registered");
     125       69866 : }
     126             : 
     127             : void
     128       69810 : Registry::addAppDataFilePath(const std::string & app_name, const std::string & app_path)
     129             : {
     130             :   // split the *App.C filename from its containing directory
     131       69810 :   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       69810 :   addDataFilePath(app_name, MooseUtils::pathjoin(dir, "../../data"));
     135       69810 : }
     136             : 
     137             : void
     138           2 : Registry::addDeprecatedAppDataFilePath(const std::string & app_path)
     139             : {
     140           2 :   const auto app_name = appNameFromAppPath(app_path);
     141           2 :   mooseDeprecated("In ",
     142             :                   app_path,
     143             :                   ":\nregisterDataFilePath() is deprecated. Use registerAppDataFilePath(\"",
     144             :                   app_name,
     145             :                   "\") instead.");
     146           2 :   addAppDataFilePath(app_name, app_path);
     147           2 : }
     148             : 
     149             : std::string
     150           8 : Registry::getDataFilePath(const std::string & name)
     151             : {
     152           8 :   const auto & dfps = getRegistry()._data_file_paths;
     153           8 :   const auto it = dfps.find(name);
     154           8 :   if (it == dfps.end())
     155           2 :     mooseError("Registry::getDataFilePath(): A data file path for '", name, "' is not registered");
     156          12 :   return it->second;
     157             : }
     158             : 
     159             : void
     160       69809 : Registry::addRepository(const std::string & repo_name, const std::string & repo_url)
     161             : {
     162       69809 :   auto & repos = getRegistry()._repos;
     163       69809 :   const auto [it, inserted] = repos.emplace(repo_name, repo_url);
     164       69809 :   if (!inserted && it->second != repo_url)
     165           2 :     mooseError("Registry::registerRepository(): The repository '",
     166             :                repo_name,
     167             :                "' is already registered with a different URL '",
     168           2 :                it->second,
     169             :                "'.");
     170       69807 : }
     171             : 
     172             : const std::string &
     173          12 : Registry::getRepositoryURL(const std::string & repo_name)
     174             : {
     175          12 :   const auto & repos = getRegistry()._repos;
     176          12 :   if (const auto it = repos.find(repo_name); it != repos.end())
     177          10 :     return it->second;
     178           2 :   mooseError("Registry::getRepositoryURL(): The repository '", repo_name, "' is not registered.");
     179             : }
     180             : 
     181             : std::string
     182       69866 : 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       69866 :       MooseUtils::pathjoin(Moose::getExecutablePath(), "..", "share", name, "data");
     193       69866 :   if (MooseUtils::checkFileReadable(installed_path, false, false, false))
     194           0 :     return MooseUtils::canonicalPath(installed_path);
     195             : 
     196             :   // In tree data
     197       69866 :   if (MooseUtils::checkFileReadable(in_tree_path, false, false, false))
     198       69864 :     return MooseUtils::canonicalPath(in_tree_path);
     199             : 
     200           2 :   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       69866 : }
     207             : 
     208             : std::string
     209           6 : 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           6 :   std::smatch match;
     218           6 :   if (std::regex_search(app_path, match, std::regex("\\/([a-zA-Z0-9_]+)App\\.C$")))
     219             :   {
     220           4 :     std::string name = match[1];                                        // FooBarBaz
     221           4 :     name = std::regex_replace(name, std::regex("(?!^)([A-Z])"), "_$1"); // Foo_Bar_Baz
     222           4 :     name = MooseUtils::toLower(name);                                   // foo_bar_baz
     223           8 :     return name;
     224           4 :   }
     225             : 
     226           2 :   mooseError(
     227             :       "Registry::appNameFromAppPath(): Failed to parse application name from '", app_path, "'");
     228           6 : }

Generated by: LCOV version 1.14