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 : }
|