https://mooseframework.inl.gov
Registry.C
Go to the documentation of this file.
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 &
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  if (!registry_singleton)
29  registry_singleton = new Registry();
30  return *registry_singleton;
31 }
32 
33 void
34 Registry::registerObjectsTo(Factory & f, const std::set<std::string> & labels)
35 {
36  auto & r = getRegistry();
37 
38  for (const auto & label : labels)
39  {
40  r._known_labels.insert(label);
41  if (r._per_label_objects.count(label) == 0)
42  continue;
43 
44  for (const auto & obj : r._per_label_objects[label])
45  {
46  const auto name = obj->name();
47  r._name_to_entry[name] = obj;
48 
49  f.reg(obj);
50  if (!obj->_alias.empty())
51  f.associateNameToClass(name, obj->_classname);
52  }
53  }
54 }
55 
56 const RegistryEntryBase &
57 Registry::objData(const std::string & name)
58 {
59  auto & r = getRegistry();
60 
61  if (const auto it = r._name_to_entry.find(name); it != r._name_to_entry.end())
62  return *it->second;
63  else
64  mooseError("Object ", name, " is not registered yet");
65 }
66 
67 void
68 Registry::registerActionsTo(ActionFactory & f, const std::set<std::string> & labels)
69 {
70  auto & r = getRegistry();
71 
72  for (const auto & label : labels)
73  {
74  r._known_labels.insert(label);
75  if (r._per_label_actions.count(label) == 0)
76  continue;
77 
78  for (const auto & obj : r._per_label_actions[label])
79  f.reg(obj);
80  }
81 }
82 
83 char
84 Registry::addKnownLabel(const std::string & label)
85 {
86  getRegistry()._known_labels.insert(label);
87  return 0;
88 }
89 
90 void
91 Registry::addDataFilePath(const std::string & name, const std::string & in_tree_path)
92 {
93  if (!std::regex_search(name, std::regex("\\w+")))
94  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  const std::string folder = std::filesystem::path(in_tree_path).filename().c_str();
99  if (folder != "data")
100  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  const auto path = determineDataFilePath(name, in_tree_path);
110 
111  auto & dfp = getRegistry()._data_file_paths;
112  const auto it = dfp.find(name);
113  // Not registered yet
114  if (it == dfp.end())
115  dfp.emplace(name, path);
116  // Registered, but with a different value
117  else if (it->second != path)
118  mooseError("While registering data file path '",
119  path,
120  "' for '",
121  name,
122  "': the path '",
123  it->second,
124  "' is already registered");
125 }
126 
127 void
128 Registry::addAppDataFilePath(const std::string & app_name, const std::string & app_path)
129 {
130  // split the *App.C filename from its containing directory
131  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  addDataFilePath(app_name, MooseUtils::pathjoin(dir, "../../data"));
135 }
136 
137 void
138 Registry::addDeprecatedAppDataFilePath(const std::string & app_path)
139 {
140  const auto app_name = appNameFromAppPath(app_path);
141  mooseDeprecated("In ",
142  app_path,
143  ":\nregisterDataFilePath() is deprecated. Use registerAppDataFilePath(\"",
144  app_name,
145  "\") instead.");
146  addAppDataFilePath(app_name, app_path);
147 }
148 
149 std::string
150 Registry::getDataFilePath(const std::string & name)
151 {
152  const auto & dfps = getRegistry()._data_file_paths;
153  const auto it = dfps.find(name);
154  if (it == dfps.end())
155  mooseError("Registry::getDataFilePath(): A data file path for '", name, "' is not registered");
156  return it->second;
157 }
158 
159 void
160 Registry::addRepository(const std::string & repo_name, const std::string & repo_url)
161 {
162  auto & repos = getRegistry()._repos;
163  const auto [it, inserted] = repos.emplace(repo_name, repo_url);
164  if (!inserted && it->second != repo_url)
165  mooseError("Registry::registerRepository(): The repository '",
166  repo_name,
167  "' is already registered with a different URL '",
168  it->second,
169  "'.");
170 }
171 
172 const std::string &
173 Registry::getRepositoryURL(const std::string & repo_name)
174 {
175  const auto & repos = getRegistry()._repos;
176  if (const auto it = repos.find(repo_name); it != repos.end())
177  return it->second;
178  mooseError("Registry::getRepositoryURL(): The repository '", repo_name, "' is not registered.");
179 }
180 
181 std::string
182 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  MooseUtils::pathjoin(Moose::getExecutablePath(), "..", "share", name, "data");
193  if (MooseUtils::checkFileReadable(installed_path, false, false, false))
194  return MooseUtils::canonicalPath(installed_path);
195 
196  // In tree data
197  if (MooseUtils::checkFileReadable(in_tree_path, false, false, false))
198  return MooseUtils::canonicalPath(in_tree_path);
199 
200  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 }
207 
208 std::string
209 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  std::smatch match;
218  if (std::regex_search(app_path, match, std::regex("\\/([a-zA-Z0-9_]+)App\\.C$")))
219  {
220  std::string name = match[1]; // FooBarBaz
221  name = std::regex_replace(name, std::regex("(?!^)([A-Z])"), "_$1"); // Foo_Bar_Baz
222  name = MooseUtils::toLower(name); // foo_bar_baz
223  return name;
224  }
225 
226  mooseError(
227  "Registry::appNameFromAppPath(): Failed to parse application name from '", app_path, "'");
228 }
static std::string appNameFromAppPath(const std::string &app_path)
Internal helper for getting an application name from its path, for example: /path/to/FooBarBazApp.C -> foo_bar_baz, for use in addDeprecatedAppDataFilePath.
Definition: Registry.C:209
static const RegistryEntryBase & objData(const std::string &name)
Definition: Registry.C:57
static Registry & getRegistry()
Get the global Registry singleton.
Definition: Registry.C:23
std::string toLower(const std::string &name)
Convert supplied string to lower case.
Generic factory class for build all sorts of objects.
Definition: Factory.h:28
static std::string getDataFilePath(const std::string &name)
Gets a data path for the registered name.
Definition: Registry.C:150
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:302
static void addAppDataFilePath(const std::string &app_name, const std::string &app_path)
register search paths for an application (path determined relative to app_path); app_path should be p...
Definition: Registry.C:128
std::string getExecutablePath()
This function returns the PATH of the running executable.
static std::string determineDataFilePath(const std::string &name, const std::string &in_tree_path)
Internal helper for determing a root data file path (in-tree vs installed)
Definition: Registry.C:182
void reg(std::shared_ptr< RegistryEntryBase > obj)
Definition: ActionFactory.C:21
std::pair< std::filesystem::path, std::filesystem::path > splitFileName(const T &full_file)
Function for splitting path and filename.
Definition: MooseUtils.h:261
static void registerObjectsTo(Factory &f, const std::set< std::string > &labels)
This registers all MooseObjects known to the registry that have the given label(s) with the factory f...
Definition: Registry.C:34
Registry()
Definition: Registry.h:284
virtual const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:57
void reg(std::shared_ptr< RegistryEntryBase > obj)
Definition: Factory.C:23
void associateNameToClass(const std::string &name, const std::string &class_name)
Associates an object name with a class name.
Definition: Factory.C:266
static void registerActionsTo(ActionFactory &f, const std::set< std::string > &labels)
This registers all Actions known to the registry that have the given label(s) with the factory f...
Definition: Registry.C:68
std::map< std::string, std::string > _data_file_paths
Data file registry; name -> in-tree path.
Definition: Registry.h:318
std::string canonicalPath(const std::string &path)
Gets the canonical path of the given path.
Definition: MooseUtils.C:1266
Specialized factory for generic Action System objects.
Definition: ActionFactory.h:50
bool checkFileReadable(const std::string &filename, bool check_line_endings=false, bool throw_on_unreadable=true, bool check_for_git_lfs_pointer=true)
Checks to see if a file is readable (exists and permissions)
Definition: MooseUtils.C:250
static void addRepository(const std::string &repo_name, const std::string &repo_url)
register a repository
Definition: Registry.C:160
void mooseDeprecated(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:353
std::set< std::string > _known_labels
Definition: Registry.h:316
std::filesystem::path pathjoin(const std::filesystem::path &p)
Definition: MooseUtils.C:59
std::map< std::string, std::string > _repos
Repository name -> repository URL; used for mooseDocumentedError.
Definition: Registry.h:320
static const std::string & getRepositoryURL(const std::string &repo_name)
Returns the repository URL associated with repo_name.
Definition: Registry.C:173
static void addDeprecatedAppDataFilePath(const std::string &app_path)
deprecated method; use addAppDataFilePath instead
Definition: Registry.C:138
The registry is used as a global singleton to collect information on all available MooseObject and Ac...
Definition: Registry.h:161
static char addKnownLabel(const std::string &label)
addKnownLabel whitelists a label as valid for purposes of the checkLabels function.
Definition: Registry.C:84
static void addDataFilePath(const std::string &name, const std::string &in_tree_path)
register general search paths (folder name must be data)
Definition: Registry.C:91