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 <boost/format.hpp>
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 {
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 {
270 constexpr bool noDictionaryFactories = false;
271
272 StatusCode createComponent (std::unique_ptr<AsgComponent>& component,
273 const std::string& type,
274 const std::string& name,
275 const std::string& newCommand)
276 {
277 using namespace msgComponentConfig;
278
279 const auto *factory = getComponentFactory (type);
280 if (factory)
281 {
282 ANA_MSG_DEBUG ("using registered factory for type " << type);
283 component = (*factory) (name);
284 if (component == nullptr)
285 {
286 ANA_MSG_ERROR ("factory for type " << type << " returned a null pointer");
287 return StatusCode::FAILURE;
288 }
289 return StatusCode::SUCCESS;
290 }
291
292 if (noDictionaryFactories)
293 {
294 ANA_MSG_ERROR ("no component factory for type " << type << " (dictionary factories disabled)");
295 return StatusCode::FAILURE;
296 }
297
298 ANA_MSG_DEBUG ("using dictionary as factory for type " << type);
299
300 // Load the ROOT dictionary, this is needed to be able to
301 // instantiate the component below, i.e. the code below won't load
302 // dictionaries not already loaded
303 TClass* componentClass = TClass::GetClass (type.c_str());
304 if (!componentClass)
305 {
306 ATH_MSG_ERROR ("Unable to load class dictionary for type " << type);
307 return StatusCode::FAILURE;
308 }
309
310 AsgComponent *comp = reinterpret_cast<AsgComponent*>
311 (gInterpreter->Calc(("dynamic_cast<asg::AsgComponent*>(" + (boost::format (newCommand) % type % name).str() + ")").c_str()));
312 if (comp == nullptr)
313 {
314 ANA_MSG_ERROR ("failed to create component of type " << type);
315 ANA_MSG_ERROR ("make sure you created a dictionary for your component");
316 return StatusCode::FAILURE;
317 }
318 component.reset (comp);
319
320 return StatusCode::SUCCESS;
321 }
322 }
323
324
325
326 template<> StatusCode AsgComponentConfig ::
327 makeComponentExpert<AsgComponent> (std::unique_ptr<AsgComponent>& component,
328 const std::string& newCommand,
329 bool nestedNames, std::string prefix) const
330 {
331 using namespace msgComponentConfig;
332
333 ANA_CHECK (checkTypeName (nestedNames));
334
335 std::string name = prefix + m_name;
336
337 if (!createComponent (component, m_type, name, newCommand).isSuccess())
338 return StatusCode::FAILURE;
339
340 for (auto& toolInfo : m_privateTools)
341 {
342 ToolHandle<AsgTool> th (toolInfo.first, component.get());
343 std::shared_ptr<void> mycleanup;
344 if (AsgToolConfig(toolInfo.second.m_config).makeTool (th, mycleanup).isFailure())
345 {
346 ANA_MSG_ERROR ("failed to create subtool \"" << toolInfo.first << "\" on component \"" << component->name() << "\"");
347 return StatusCode::FAILURE;
348 }
349 component->addCleanup (mycleanup);
350 if (toolInfo.second.m_propName.empty())
351 {
352 if (component->setProperty (toolInfo.first, th->name()).isFailure())
353 {
354 ANA_MSG_ERROR ("failed to set ToolHandle property \"" << toolInfo.first << "\" on component \"" << component->name() << "\"");
355 return StatusCode::FAILURE;
356 }
357 }
358 }
359
360 for (const auto& toolArray : m_toolArrays)
361 {
362 std::vector<std::string> valueArray;
363 for (const auto& tool : toolArray.second)
364 valueArray.emplace_back (component->name() + "." + tool);
365 std::string valueString;
366 ANA_CHECK (asg::detail::GetCastStringHelper<std::vector<std::string>>::get (valueArray, valueString));
367 ANA_CHECK (component->setProperty (toolArray.first, valueString));
368 }
369
370 for (auto& property : m_propertyValues)
371 {
372 ANA_CHECK (component->setProperty (property.first, property.second));
373 }
374
375 ANA_MSG_DEBUG ("Created component of type " << m_type);
376 return StatusCode::SUCCESS;
377 }
378
379
380
381#else
382
383
384
385 StatusCode AsgComponentConfig ::
386 configureComponentExpert (const std::string& prefix,
387 bool nestedNames) const
388 {
389 using namespace msgComponentConfig;
390
391 ANA_CHECK (checkTypeName (nestedNames));
392
393 ServiceHandle<Gaudi::Interfaces::IOptionsSvc> joSvc("JobOptionsSvc","AsgComponentConfig");
394 ANA_CHECK (joSvc.retrieve());
395
396 for (const auto& tool : m_privateTools)
397 {
398 ANA_CHECK (tool.second.m_config.configureComponentExpert (prefix + m_name + ".", true));
399 if (tool.second.m_propName.empty())
400 {
401 std::string toolPath = prefix + m_name + "." + tool.first;
402 joSvc->set (toolPath, tool.second.m_config.typeAndName());
403 }
404 }
405
406 for (const auto& toolArray : m_toolArrays)
407 {
408 std::vector<std::string> valueArray;
409 for (const auto& tool : toolArray.second)
410 {
411 auto toolConfig = m_privateTools.find (tool);
412 if (toolConfig == m_privateTools.end())
413 {
414 ANA_MSG_ERROR ("Couldn't find private tool with name \"" << tool << "\"");
415 ANA_MSG_ERROR ("This is an internal inconsistency!");
416 return StatusCode::FAILURE;
417 }
418 valueArray.push_back (toolConfig->second.m_config.typeAndName());
419 }
420 std::string valueString = Gaudi::Utils::toString (valueArray);
421 std::string propertyPath = prefix + m_name + "." + toolArray.first;
422 joSvc->set (propertyPath, valueString);
423 }
424
425 for (const auto& property : m_propertyValues)
426 {
427 std::string propertyPath = prefix + m_name + "." + property.first;
428 joSvc->set (propertyPath, property.second);
429 }
430
431 return StatusCode::SUCCESS;
432 }
433
434#endif
435}
#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
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:130
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177
::StatusCode StatusCode
StatusCode definition for legacy code.
access the configuration for the given subtool