ATLAS Offline Software
Loading...
Searching...
No Matches
AsgComponentConfig.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8
9//
10// includes
11//
12
14
16#include <regex>
17
18#ifdef XAOD_STANDALONE
19
22#include <AsgTools/AsgTool.h>
24#include <TInterpreter.h>
25#include <format>
26
27#else
28
29#include "Gaudi/Interfaces/IOptionsSvc.h"
30#include <GaudiKernel/ServiceHandle.h>
31
32#endif
33
34//
35// method implementations
36//
37
38namespace asg
39{
40 namespace
41 {
48 std::string makeArrayName (const std::string& name, std::size_t index)
49 {
50 return name + "@" + std::to_string (index);
51 }
52 }
53
54
55 AsgComponentConfig ::
56 AsgComponentConfig (const std::string& val_typeAndName)
57 {
58 setTypeAndName (val_typeAndName);
59 }
60
61
62
63 bool AsgComponentConfig ::
64 empty () const noexcept
65 {
66 return
67 m_type.empty() && m_name.empty() &&
68 m_privateTools.empty() && m_propertyValues.empty();
69 }
70
71
72
73 const std::string& AsgComponentConfig ::
74 type () const noexcept
75 {
76 return m_type;
77 }
78
79
80
81 void AsgComponentConfig ::
82 setType (const std::string& val_type)
83 {
84 m_type = val_type;
85 }
86
87
88
89 const std::string& AsgComponentConfig ::
90 name () const noexcept
91 {
92 return m_name;
93 }
94
95
96
97 void AsgComponentConfig ::
98 setName (const std::string& val_name)
99 {
100 m_name = val_name;
101 }
102
103
104
105 std::string AsgComponentConfig ::
106 typeAndName () const
107 {
108 if (m_name == m_type)
109 return m_name;
110 return m_type + "/" + m_name;
111 }
112
113
114
115 void AsgComponentConfig ::
116 setTypeAndName (const std::string& val_typeAndName)
117 {
118 const auto split = val_typeAndName.find ('/');
119 if (split == std::string::npos)
120 {
121 setType (val_typeAndName);
122 setName (val_typeAndName);
123 } else
124 {
125 setType (val_typeAndName.substr (0,split));
126 setName (val_typeAndName.substr (split+1));
127 }
128 }
129
130
131
132 void AsgComponentConfig ::
133 setPropertyFromString (const std::string& name,
134 const std::string& value)
135 {
136 auto split = name.find ('.');
137 if (split == std::string::npos)
138 {
139 m_propertyValues[name] = value;
140 } else
141 {
142 auto subtool = accessSubtool (name, split);
143 subtool.config->setPropertyFromString (subtool.name, value);
144 }
145 }
146
147
148
149 StatusCode AsgComponentConfig ::
150 createPrivateTool (const std::string& name,
151 const std::string& toolType)
152 {
153 return addPrivateTool (name, AsgComponentConfig(toolType + "/" + name));
154 }
155
156
157
158 std::string AsgComponentConfig ::
159 createPrivateToolInArray (const std::string& name,
160 const std::string& toolType)
161 {
162 return addPrivateToolInArray (name, AsgComponentConfig(toolType + "/" + name));
163 }
164
165
166
167 StatusCode AsgComponentConfig ::
168 addPrivateTool (const std::string& name,
169 AsgComponentConfig toolConfig)
170 {
171 using namespace msgComponentConfig;
172
173 auto split = name.find ('.');
174 if (split == std::string::npos)
175 {
176 toolConfig.setName (name);
177 m_privateTools[name] = {std::move(toolConfig), ""};
178 return StatusCode::SUCCESS;
179 } else
180 {
181 auto subtool = accessSubtool (name, split);
182 return subtool.config->addPrivateTool (subtool.name, std::move (toolConfig));
183 }
184 }
185
186
187
188 std::string AsgComponentConfig ::
189 addPrivateToolInArray (const std::string& name,
190 AsgComponentConfig toolConfig)
191 {
192 using namespace msgComponentConfig;
193
194 auto split = name.find ('.');
195 if (split == std::string::npos)
196 {
197 auto& arrayData = m_toolArrays[name];
198 auto myname = makeArrayName (name, arrayData.size());
199 toolConfig.setName (myname);
200 m_privateTools[myname] = {std::move(toolConfig), name};
201 arrayData.push_back (myname);
202 return myname;
203 } else
204 {
205 auto subtool = accessSubtool (name, split);
206 return subtool.prefix + subtool.config
207 ->addPrivateToolInArray (subtool.name, std::move (toolConfig));
208 }
209 }
210
211
212
213 StatusCode AsgComponentConfig ::
214 checkTypeName (bool nestedNames) const
215 {
216 using namespace msgComponentConfig;
217
218 std::regex typeExpr ("[A-Za-z_][A-Za-z0-9_]*(::[A-Za-z_][A-Za-z0-9_]*)*");
219 if (!std::regex_match (m_type, typeExpr))
220 {
221 ANA_MSG_ERROR ("type \"" << m_type << "\" does not match format expression");
222 return StatusCode::FAILURE;
223 }
224 std::regex nameExpr;
225 if (nestedNames)
226 nameExpr = std::regex ("[A-Za-z_][A-Za-z0-9_]*(\\.[A-Za-z_][A-Za-z0-9_]*)*(@[0-9]+)?");
227 else
228 nameExpr = std::regex ("[A-Za-z_][A-Za-z0-9_]*(@[0-9]+)?");
229 if (!std::regex_match (m_name, nameExpr))
230 {
231 ANA_MSG_ERROR ("name \"" << m_name << "\" does not match format expression");
232 return StatusCode::FAILURE;
233 }
234 return StatusCode::SUCCESS;
235 }
236
237
238
240 accessSubtool (const std::string& name, std::size_t split)
241 {
242 AccessSubtoolData result;
243 auto subtool = m_privateTools.find (name.substr (0, split));
244 if (subtool == m_privateTools.end())
245 throw std::runtime_error ("trying to access unknown private tool: " + name.substr (0, split));
246 result.config = &(subtool->second.m_config);
247 result.prefix = name.substr (0, split + 1);
248 result.name = name.substr (split + 1);
249 return result;
250 }
251
252
253
254#ifdef XAOD_STANDALONE
255 namespace
256 {
257 std::string convert_boost_format_to_std_format(const std::string& s) {
258 std::string out = s;
259 out = std::regex_replace(out, std::regex("\\{"), "{{");
260 out = std::regex_replace(out, std::regex("\\}"), "}}");
261 // Convert %x% to {}
262 out = std::regex_replace(out, std::regex("%[0-9]+%"), "{}");
263 return out;
264 }
278 constexpr bool noDictionaryFactories = false;
279
280 StatusCode createComponent (std::unique_ptr<AsgComponent>& component,
281 const std::string& type,
282 const std::string& name,
283 const std::string& newCommand)
284 {
285 using namespace msgComponentConfig;
286
287 const auto *factory = getComponentFactory (type);
288 if (factory)
289 {
290 ANA_MSG_DEBUG ("using registered factory for type " << type);
291 component = (*factory) (name);
292 if (component == nullptr)
293 {
294 ANA_MSG_ERROR ("factory for type " << type << " returned a null pointer");
295 return StatusCode::FAILURE;
296 }
297 return StatusCode::SUCCESS;
298 }
299
300 if (noDictionaryFactories)
301 {
302 ANA_MSG_ERROR ("no component factory for type " << type << " (dictionary factories disabled)");
303 return StatusCode::FAILURE;
304 }
305
306 ANA_MSG_DEBUG ("using dictionary as factory for type " << type);
307
308 // Load the ROOT dictionary, this is needed to be able to
309 // instantiate the component below, i.e. the code below won't load
310 // dictionaries not already loaded
311 TClass* componentClass = TClass::GetClass (type.c_str());
312 if (!componentClass)
313 {
314 ATH_MSG_ERROR ("Unable to load class dictionary for type " << type);
315 return StatusCode::FAILURE;
316 }
317 std::string fmt = convert_boost_format_to_std_format(newCommand);
318 std::string cmd = std::vformat(fmt, std::make_format_args(type, name));
319 std::string expr = std::format("dynamic_cast<asg::AsgComponent*>({})", cmd);
320 AsgComponent *comp = reinterpret_cast<AsgComponent*>(gInterpreter->Calc(expr.c_str()));
321 if (comp == nullptr)
322 {
323 ANA_MSG_ERROR ("failed to create component of type " << type);
324 ANA_MSG_ERROR ("make sure you created a dictionary for your component");
325 return StatusCode::FAILURE;
326 }
327 component.reset (comp);
328
329 return StatusCode::SUCCESS;
330 }
331 }
332
333
334
335 template<> StatusCode AsgComponentConfig ::
336 makeComponentExpert<AsgComponent> (std::unique_ptr<AsgComponent>& component,
337 const std::string& newCommand,
338 bool nestedNames, std::string prefix) const
339 {
340 using namespace msgComponentConfig;
341
342 ANA_CHECK (checkTypeName (nestedNames));
343
344 std::string name = prefix + m_name;
345
346 if (!createComponent (component, m_type, name, newCommand).isSuccess())
347 return StatusCode::FAILURE;
348
349 for (auto& toolInfo : m_privateTools)
350 {
351 ToolHandle<AsgTool> th (toolInfo.first, component.get());
352 std::shared_ptr<void> mycleanup;
353 if (AsgToolConfig(toolInfo.second.m_config).makeTool (th, mycleanup).isFailure())
354 {
355 ANA_MSG_ERROR ("failed to create subtool \"" << toolInfo.first << "\" on component \"" << component->name() << "\"");
356 return StatusCode::FAILURE;
357 }
358 component->addCleanup (mycleanup);
359 if (toolInfo.second.m_propName.empty())
360 {
361 if (component->setProperty (toolInfo.first, th->name()).isFailure())
362 {
363 ANA_MSG_ERROR ("failed to set ToolHandle property \"" << toolInfo.first << "\" on component \"" << component->name() << "\"");
364 return StatusCode::FAILURE;
365 }
366 }
367 }
368
369 for (const auto& toolArray : m_toolArrays)
370 {
371 std::vector<std::string> valueArray;
372 for (const auto& tool : toolArray.second)
373 valueArray.emplace_back (component->name() + "." + tool);
374 std::string valueString;
375 ANA_CHECK (asg::detail::GetCastStringHelper<std::vector<std::string>>::get (valueArray, valueString));
376 ANA_CHECK (component->setProperty (toolArray.first, valueString));
377 }
378
379 for (auto& property : m_propertyValues)
380 {
381 ANA_CHECK (component->setProperty (property.first, property.second));
382 }
383
384 ANA_MSG_DEBUG ("Created component of type " << m_type);
385 return StatusCode::SUCCESS;
386 }
387
388
389
390#else
391
392
393
394 StatusCode AsgComponentConfig ::
395 configureComponentExpert (const std::string& prefix,
396 bool nestedNames) const
397 {
398 using namespace msgComponentConfig;
399
400 ANA_CHECK (checkTypeName (nestedNames));
401
402 ServiceHandle<Gaudi::Interfaces::IOptionsSvc> joSvc("JobOptionsSvc","AsgComponentConfig");
403 ANA_CHECK (joSvc.retrieve());
404
405 for (const auto& tool : m_privateTools)
406 {
407 ANA_CHECK (tool.second.m_config.configureComponentExpert (prefix + m_name + ".", true));
408 if (tool.second.m_propName.empty())
409 {
410 std::string toolPath = prefix + m_name + "." + tool.first;
411 joSvc->set (toolPath, tool.second.m_config.typeAndName());
412 }
413 }
414
415 for (const auto& toolArray : m_toolArrays)
416 {
417 std::vector<std::string> valueArray;
418 for (const auto& tool : toolArray.second)
419 {
420 auto toolConfig = m_privateTools.find (tool);
421 if (toolConfig == m_privateTools.end())
422 {
423 ANA_MSG_ERROR ("Couldn't find private tool with name \"" << tool << "\"");
424 ANA_MSG_ERROR ("This is an internal inconsistency!");
425 return StatusCode::FAILURE;
426 }
427 valueArray.push_back (toolConfig->second.m_config.typeAndName());
428 }
429 std::string valueString = Gaudi::Utils::toString (valueArray);
430 std::string propertyPath = prefix + m_name + "." + toolArray.first;
431 joSvc->set (propertyPath, valueString);
432 }
433
434 for (const auto& property : m_propertyValues)
435 {
436 std::string propertyPath = prefix + m_name + "." + property.first;
437 joSvc->set (propertyPath, property.second);
438 }
439
440 return StatusCode::SUCCESS;
441 }
442
443#endif
444}
#define ATH_MSG_ERROR(x)
#define ANA_MSG_ERROR(xmsg)
Macro printing error messages.
#define ANA_MSG_DEBUG(xmsg)
Macro printing debug messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
const char *const fmt
std::string addPrivateToolInArray(const std::string &name, AsgComponentConfig toolConfig)
the array version of addPrivateTool
std::string m_type
the value of type
std::map< std::string, std::string > m_propertyValues
the map of property values
std::map< std::string, details::AsgComponentPrivateToolConfig > m_privateTools
the map of (private) tools to create
const std::string & name() const noexcept
the name of the component
void setType(const std::string &val_type)
set the value of type
void setTypeAndName(const std::string &val_typeAndName)
set type and name at the same time
AsgComponentConfig()=default
standard constructor
StatusCode checkTypeName(bool nestedNames) const
check that the type and name members have the correct format
AccessSubtoolData accessSubtool(const std::string &name, std::size_t split)
StatusCode addPrivateTool(const std::string &name, AsgComponentConfig toolConfig)
add a private tool from the given configuration
std::string m_name
the value of name
void setName(const std::string &val_name)
set the value of name
std::map< std::string, std::vector< std::string > > m_toolArrays
the map of (private) tool handle arrays to manage, and the tools they contain
an object that can create a AsgTool
::StatusCode makeTool(ToolHandle< T > &toolHandle, std::shared_ptr< void > &cleanup, bool allowNestedName=false) const
make a tool with the given configuration
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:132
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
std::string m_name
The primary name part of this expression.
::StatusCode StatusCode
StatusCode definition for legacy code.
access the configuration for the given subtool