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 #include "Capabilities.h"
16 
17 #include "libmesh/libmesh_common.h"
18 
19 #include <memory>
20 #include <filesystem>
21 #include <regex>
22 
23 Registry &
25 {
26  // We need a naked new here (_not_ a smart pointer or object instance) due to what seems like a
27  // bug in clang's static object destruction when using dynamic library loading.
28  static Registry * registry_singleton = nullptr;
29  if (!registry_singleton)
30  registry_singleton = new Registry();
31  return *registry_singleton;
32 }
33 
34 void
35 Registry::registerObjectsTo(Factory & f, const std::set<std::string> & labels)
36 {
37  auto & r = getRegistry();
38 
39  for (const auto & label : labels)
40  {
41  r._known_labels.insert(label);
42  if (r._per_label_objects.count(label) == 0)
43  continue;
44 
45  for (const auto & obj : r._per_label_objects[label])
46  {
47  const auto name = obj->name();
48  r._name_to_entry[name] = obj;
49 
50  f.reg(obj);
51  if (!obj->_alias.empty())
52  f.associateNameToClass(name, obj->_classname);
53  }
54  }
55 }
56 
57 const RegistryEntryBase &
58 Registry::objData(const std::string & name)
59 {
60  auto & r = getRegistry();
61 
62  if (const auto it = r._name_to_entry.find(name); it != r._name_to_entry.end())
63  return *it->second;
64  else
65  mooseError("Object ", name, " is not registered yet");
66 }
67 
68 void
69 Registry::registerActionsTo(ActionFactory & f, const std::set<std::string> & labels)
70 {
71  auto & r = getRegistry();
72 
73  for (const auto & label : labels)
74  {
75  r._known_labels.insert(label);
76  if (r._per_label_actions.count(label) == 0)
77  continue;
78 
79  for (const auto & obj : r._per_label_actions[label])
80  f.reg(obj);
81  }
82 }
83 
84 char
85 Registry::addKnownLabel(const std::string & label)
86 {
87  getRegistry()._known_labels.insert(label);
88  return 0;
89 }
90 
91 void
92 Registry::addDataFilePath(const std::string & name,
93  const std::string & in_tree_path,
94  const bool is_app /* = true */,
95  const std::optional<std::string> & info /* = {} */)
96 {
98 
99  // Enforce that the folder is called "data", because we rely on the installed path
100  // to be within PREFIX/share/<name>/data (see determineDataFilePath())
101  if (is_app)
102  {
103  const std::string folder = std::filesystem::path(in_tree_path).filename().c_str();
104  if (folder != "data")
105  mooseError("While registering data file path '",
106  in_tree_path,
107  "' for '",
108  name,
109  "': The folder must be named 'data' and it is named '",
110  folder,
111  "'");
112  }
113 
114  // Find either the installed or in-tree path
115  const auto path = determineDataFilePath(name, in_tree_path);
116 
117  auto & dfp = getRegistry()._data_file_paths;
118  const auto it = dfp.find(name);
119  // Not registered yet
120  if (it == dfp.end())
121  {
122  dfp.emplace(name, path);
124  }
125  // Registered, but with a different value
126  else if (it->second != path)
127  mooseError("While registering data file path '",
128  path,
129  "' for '",
130  name,
131  "': the path '",
132  it->second,
133  "' is already registered");
134 }
135 
136 void
137 Registry::addMissingDataFilePath(const std::string & name, const std::string & info)
138 {
141 }
142 
143 void
144 Registry::addAppDataFilePath(const std::string & app_name, const std::string & app_path)
145 {
146  // split the *App.C filename from its containing directory
147  const auto dir = MooseUtils::splitFileName(app_path).first;
148  // This works for both build/unity_src/ and src/base/ as the *App.C file location,
149  // in case __FILE__ doesn't get overriden in unity build
150  addDataFilePath(app_name, MooseUtils::pathjoin(dir, "../../data"));
151 }
152 
153 void
154 Registry::addDeprecatedAppDataFilePath(const std::string & app_path)
155 {
156  const auto app_name = appNameFromAppPath(app_path);
157  mooseDeprecated("In ",
158  app_path,
159  ":\nregisterDataFilePath() is deprecated. Use registerAppDataFilePath(\"",
160  app_name,
161  "\") instead.");
162  addAppDataFilePath(app_name, app_path);
163 }
164 
165 std::string
166 Registry::getDataFilePath(const std::string & name)
167 {
168  const auto & dfps = getRegistry()._data_file_paths;
169  const auto it = dfps.find(name);
170  if (it == dfps.end())
171  mooseError("Registry::getDataFilePath(): A data file path for '", name, "' is not registered");
172  return it->second;
173 }
174 
175 void
176 Registry::addRepository(const std::string & repo_name, const std::string & repo_url)
177 {
178  auto & repos = getRegistry()._repos;
179  const auto [it, inserted] = repos.emplace(repo_name, repo_url);
180  if (!inserted && it->second != repo_url)
181  mooseError("Registry::registerRepository(): The repository '",
182  repo_name,
183  "' is already registered with a different URL '",
184  it->second,
185  "'.");
186 }
187 
188 const std::string &
189 Registry::getRepositoryURL(const std::string & repo_name)
190 {
191  const auto & repos = getRegistry()._repos;
192  if (const auto it = repos.find(repo_name); it != repos.end())
193  return it->second;
194  mooseError("Registry::getRepositoryURL(): The repository '", repo_name, "' is not registered.");
195 }
196 
197 std::string
198 Registry::determineDataFilePath(const std::string & name, const std::string & in_tree_path)
199 {
200  // TODO: Track whether or not the application is installed in a better way
201  // than this, which will enable us to pick one or the other based on
202  // the install state. This probably also won't work with dynamic loading, where
203  // we can't necessarily get this information from the binary (as there could be
204  // multiple binary paths)
205 
206  // Installed data
207  const auto installed_path =
208  MooseUtils::pathjoin(Moose::getExecutablePath(), "..", "share", name, "data");
209  if (MooseUtils::checkFileReadable(installed_path, false, false, false))
210  return MooseUtils::canonicalPath(installed_path);
211 
212  // In tree data
213  if (MooseUtils::checkFileReadable(in_tree_path, false, false, false))
214  return MooseUtils::canonicalPath(in_tree_path);
215 
216  mooseError("Failed to determine data file path for '",
217  name,
218  "'. Paths searched:\n\n installed: ",
219  installed_path,
220  "\n in-tree: ",
221  in_tree_path);
222 }
223 
224 std::string
225 Registry::appNameFromAppPath(const std::string & app_path)
226 {
227  // This is for deprecated use only. It assumes that the application name
228  // (binary name) in the build follows our normal naming of FooBarApp -> foo_bar.
229  // We need to convert the application source file to the above, for example:
230  // /path/to/FooBarBazApp.C -> foo_bar_baz
231  // Ideally, we would instead have the user specify this manually so that
232  // there is no ambiguity.
233  std::smatch match;
234  if (std::regex_search(app_path, match, std::regex("\\/([a-zA-Z0-9_]+)App\\.C$")))
235  {
236  std::string name = match[1]; // FooBarBaz
237  name = std::regex_replace(name, std::regex("(?!^)([A-Z])"), "_$1"); // Foo_Bar_Baz
238  name = MooseUtils::toLower(name); // foo_bar_baz
239  return name;
240  }
241 
242  mooseError(
243  "Registry::appNameFromAppPath(): Failed to parse application name from '", app_path, "'");
244 }
245 
246 void
248 {
249  if (!std::regex_search(name, std::regex("[a-z0-9_]+")))
250  mooseError("Unallowed characters in data file path name '",
251  name,
252  "'; allowed characters = a-z, 0-9, _");
253 }
254 
255 void
257  const std::optional<std::string> & path /* = {} */,
258  const std::optional<std::string> & extra_info /* = {}*/)
259 {
260  std::string doc = "Named data path '" + name + "' is ";
261  if (path)
262  doc += "available at '" + *path + "'";
263  else
264  doc += "not available";
265  if (extra_info)
266  doc += "; " + *extra_info;
267  doc += ".";
268 
269  auto & capabilities = Moose::internal::Capabilities::getCapabilities({});
270  capabilities.add("data_" + name, bool(path), doc);
271 }
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:225
static const RegistryEntryBase & objData(const std::string &name)
Definition: Registry.C:58
static Registry & getRegistry()
Get the global Registry singleton.
Definition: Registry.C:24
static void addDataFilePath(const std::string &name, const std::string &in_tree_path, const bool app=true, const std::optional< std::string > &info={})
register general search paths; "app" is whether or not the path is an app path
Definition: Registry.C:92
MPI_Info info
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:166
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
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:144
std::string getExecutablePath()
Gets the directory the running executable is on Mac OS X and linux.
static Capabilities & getCapabilities(const GetCapabilitiesPassKey)
Get the singleton Capabilities.
Definition: Capabilities.C:52
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:198
void reg(std::shared_ptr< RegistryEntryBase > obj)
Definition: ActionFactory.C:22
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:35
Registry()
Definition: Registry.h:302
void reg(std::shared_ptr< RegistryEntryBase > obj)
Definition: Factory.C:23
static void addMissingDataFilePath(const std::string &name, const std::string &info)
register a data file path as missing, along with info about how it can be added
Definition: Registry.C:137
void associateNameToClass(const std::string &name, const std::string &class_name)
Associates an object name with a class name.
Definition: Factory.C:290
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
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:69
static void addDataFilePathCapability(const std::string &name, const std::optional< std::string > &path={}, const std::optional< std::string > &extra_info={})
Add a data file path capability.
Definition: Registry.C:256
std::map< std::string, std::string > _data_file_paths
Data file registry; name -> in-tree path.
Definition: Registry.h:344
Capability & add(const std::string_view name, const Moose::Capability::Value &value, const std::string_view doc)
Add a capability.
std::string canonicalPath(const std::string &path)
Definition: MooseUtils.C:1173
Specialized factory for generic Action System objects.
Definition: ActionFactory.h:48
static void checkDataFilePathName(const std::string &name)
Check a data file path for valid characters.
Definition: Registry.C:247
static void addRepository(const std::string &repo_name, const std::string &repo_url)
register a repository
Definition: Registry.C:176
void mooseDeprecated(Args &&... args)
Emit a deprecated code/feature message with the given stringified, concatenated args.
Definition: MooseError.h:363
std::string toLower(std::string name)
Convert supplied string to lower case.
std::set< std::string > _known_labels
Definition: Registry.h:342
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:346
static const std::string & getRepositoryURL(const std::string &repo_name)
Returns the repository URL associated with repo_name.
Definition: Registry.C:189
static void addDeprecatedAppDataFilePath(const std::string &app_path)
deprecated method; use addAppDataFilePath instead
Definition: Registry.C:154
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
Definition: MooseUtils.C:254
The registry is used as a global singleton to collect information on all available MooseObject and Ac...
Definition: Registry.h:171
static char addKnownLabel(const std::string &label)
addKnownLabel whitelists a label as valid for purposes of the checkLabels function.
Definition: Registry.C:85