ATLAS Offline Software
TrigComposite_v1.icc
Go to the documentation of this file.
1 // Dear emacs, this is -*- c++ -*-
2 
3 /*
4  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 #ifndef XAODTRIGGER_VERSIONS_TRIGCOMPOSITE_V1_ICC
8 #define XAODTRIGGER_VERSIONS_TRIGCOMPOSITE_V1_ICC
9 
10 // System include(s):
11 #include <iostream>
12 #include <stdexcept>
13 
14 // xAOD include(s):
15 #include "AthContainers/tools/CurrentEventStore.h"
16 #include "AthContainers/DataVector.h"
17 #include "AthContainers/normalizedTypeinfoName.h"
18 #include "AthContainers/Accessor.h"
19 #include "xAODCore/CLASS_DEF.h"
20 
21 // In "standalone mode" xAOD::IParticleContainer doesn't have a CLID
22 // defined for it. But this code requires one to be set.
23 //
24 // The following is incredibly ugly, but this is the best that I could
25 // come up with on short notice. Note that the CLID value is copy-pasted
26 // from the IParticleContainer.h header.
27 #include "xAODBase/IParticleContainer.h"
28 #ifdef XAOD_STANDALONE
29 CLASS_DEF( xAOD::IParticleContainer, 1241842700, 1 )
30 #endif // XAOD_STANDALONE
31 
32 namespace xAOD {
33 
34  template< typename TYPE >
35  bool TrigComposite_v1::hasDetail( const std::string& name ) const {
36 
37  // Object used to check for the existence of an object:
38  ConstAccessor< TYPE > acc( name );
39 
40  // Use the Accessor object for the check:
41  return acc.isAvailable( *this );
42  }
43 
44  template< typename TYPE >
45  bool TrigComposite_v1::setDetail( const std::string& name, const TYPE& value ) {
46  // It should be pretty strange if this should fail:
47  SG::Accessor< TYPE > acc( name );
48  try {
49  acc( *this ) = value;
50  } catch(const std::exception& exc) {
51  std::cerr << "xAOD::TrigComposite_v1::setDetail ERROR Internal logic error found: [" << exc.what() << "]" << std::endl;
52  return false;
53  }
54  // Return gracefully:
55  return true;
56  }
57 
58  template< typename TYPE >
59  bool TrigComposite_v1::getDetail( const std::string& name, TYPE& value) const {
60  // Object used to access the auxiliary data:
61  ConstAccessor< TYPE > acc( name );
62 
63  if( ! acc.isAvailable( *this ) ) {
64  return false;
65  }
66  value = acc( *this );
67  return true;
68  }
69 
70  template< typename TYPE >
71  TYPE TrigComposite_v1::getDetail( const std::string& name ) const {
72  ConstAccessor< TYPE > acc( name );
73  return acc( *this );
74  }
75 
76  template< class CONTAINER >
77  bool
78  TrigComposite_v1::setObjectLink( const std::string& name,
79  const ElementLink< CONTAINER >& link ) {
80 
81  // Check link has valid persistent state, i.e. hash key is not
82  // zero, otherwise attempting to access its string key will seg
83  // fault later, e.g. in remapping.
84  if( link.key() == 0 ) {
85  std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR "
86  << "link has invalid key hash of zero" << std::endl;
87  return false;
88  }
89 
90  if( ! link.isValid() ) {
91  std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR "
92  << "link is not valid" << std::endl;
93  return false;
94  }
95 
96  // Do different things depending on whether this variable already
97  // exists or not:
98  if( hasObjectLink( name ) ) {
99  // Find the right object:
100  const std::vector< std::string >& names = linkColNames();
101  for( size_t i = 0; i < names.size(); ++i ) {
102  if( names[ i ] != name ) continue;
103  // Extract the information out of the ElementLink:
104  linkColKeysNC()[ i ] = link.key();
105  linkColIndicesNC()[ i ] = link.index();
106  linkColClidsNC()[ i ] = ClassID_traits< CONTAINER >::ID();
107  // We're done:
108  return true;
109  }
110  // Some error happened...
111  std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR Internal "
112  << "logic error found" << std::endl;
113  return false;
114  } else {
115  // Add a new object:
116  linkColNamesNC().push_back( name );
117  linkColKeysNC().push_back( link.key() );
118  linkColIndicesNC().push_back( link.index() );
119  linkColClidsNC().push_back( ClassID_traits< CONTAINER >::ID() );
120  // And we're done:
121  return true;
122  }
123  }
124 
125  template< class CONTAINER >
126  ElementLink< CONTAINER >
127  TrigComposite_v1::objectLink( const std::string& name ) const {
128 
129  // Retrieve current store once (would be better to pass EventContext everywhere)
130  auto sg = SG::CurrentEventStore::store();
131 
132  // Find the right object:
133  const std::vector< std::string >& names = linkColNames();
134  for( size_t i = 0; i < names.size(); ++i ) {
135  if( names[ i ] != name ) continue;
136  checkTypes< CONTAINER >(linkColClids()[ i ], name);
137  ElementLink< CONTAINER > link( linkColKeys()[ i ],
138  linkColIndices()[ i ],
139  sg );
140 
141  if (link.isValid()) {
142  return link;
143  }
144 
145  if (isRemapped()) {
146  return ElementLink< CONTAINER >( linkColKeysRemap()[ i ],
147  linkColIndicesRemap()[ i ],
148  sg );
149  }
150 
151  return link;
152  }
153 
154  // We didn't find the link. :-(
155  throw std::runtime_error( "xAOD::TrigComposite::objectLink: No link "
156  "name \"" + name + "\" found" );
157  return ElementLink< CONTAINER >();
158  }
159 
160  template< class OBJECT >
161  const OBJECT* TrigComposite_v1::object( const std::string& name ) const {
162 
163  // Check if the link exists:
164  if( ! hasObjectLink( name ) ) {
165  return nullptr;
166  }
167 
168  // Retrieve current store once (would be better to pass EventContext everywhere)
169  auto sg = SG::CurrentEventStore::store();
170 
171  // Now look for it:
172  const std::vector< std::string >& names = linkColNames();
173  for( size_t i = 0; i < names.size(); ++i ) {
174  if( names[ i ] != name ) continue;
175  // Check that it is of the right type:
176  checkTypes< DataVector< OBJECT > >(linkColClids()[ i ], name);
177  // Create a temporary ElementLink:
178  ElementLink< DataVector< OBJECT > > link( linkColKeys()[ i ],
179  linkColIndices()[ i ],
180  sg );
181  if( link.isValid() ) {
182  return *link;
183  }
184 
185  if (isRemapped()) {
186  link = ElementLink< DataVector< OBJECT > >( linkColKeysRemap()[ i ],
187  linkColIndicesRemap()[ i ],
188  sg );
189  if( link.isValid() ) {
190  return *link;
191  }
192  }
193 
194  return nullptr;
195  }
196 
197  // There was an internal error. :-(
198  std::cerr << "xAOD::TrigComposite_v1::object ERROR Internal error "
199  << "detected" << std::endl;
200  return nullptr;
201  }
202 
203  template< class CONTAINER >
204  bool
205  TrigComposite_v1::addObjectCollectionLink( const std::string& collectionName,
206  const ElementLink< CONTAINER >& link ) {
207 
208  // No method currently provided to update or check for uniqueness of a link
209  // being added to a container.
210 
211  // Add a new object (unless it would duplicate an existing one):
212  const std::string mangledName = collectionName + s_collectionSuffix;
213  if (!hasObjectLinkExact(mangledName, link.key(), link.index(), ClassID_traits< CONTAINER >::ID())) {
214  linkColNamesNC().push_back( mangledName );
215  linkColKeysNC().push_back( link.key() );
216  linkColIndicesNC().push_back( link.index() );
217  linkColClidsNC().push_back( ClassID_traits< CONTAINER >::ID() );
218  }
219  return true;
220  }
221 
222  template< class CONTAINER >
223  bool
224  TrigComposite_v1::addObjectCollectionLinks( const std::string& collectionName,
225  const std::vector<ElementLink< CONTAINER >>& links ) {
226  // Add all links
227  for (const ElementLink< CONTAINER >& link : links ) {
228  addObjectCollectionLink( collectionName, link );
229  }
230  return true;
231  }
232 
233  template< class CONTAINER >
234  std::vector<ElementLink< CONTAINER >>
235  TrigComposite_v1::objectCollectionLinks( const std::string& collectionName ) const {
236  std::vector<ElementLink< CONTAINER >> links;
237  const std::string mangledName = collectionName + s_collectionSuffix;
238 
239  // Retrieve current store once (would be better to pass EventContext everywhere)
240  auto sg = SG::CurrentEventStore::store();
241 
242  const std::vector< std::string >& names = linkColNames();
243  for( size_t i = 0; i < names.size(); ++i ) {
244  if( names[ i ] != mangledName ) continue;
245  // Check that it is of the right type:
246  checkTypes< CONTAINER >(linkColClids()[ i ], collectionName);
247  // Construct and add the link:
248  ElementLink< CONTAINER > link(linkColKeys()[ i ],
249  linkColIndices()[ i ],
250  sg);
251  if (link.isValid()) {
252  links.push_back( link );
253  } else if (isRemapped()) {
254  link = ElementLink< CONTAINER >(linkColKeysRemap()[ i ],
255  linkColIndicesRemap()[ i ],
256  sg);
257  links.push_back( link );
258  } else {
259  links.push_back( link );
260  }
261  }
262  return links;
263  }
264 
265  template< class CONTAINER >
266  std::vector<std::string> TrigComposite_v1::getObjectNames() const {
267 
268  std::vector< std::string > returnVec;
269  const std::vector< std::string >& names = linkColNames();
270  const std::vector< uint32_t >& clids = linkColClids();
271 
272  for( size_t i = 0; i < names.size(); ++i ) {
273  if (names[i].find(s_collectionSuffix) != std::string::npos) { //Note: !=
274  continue; // ARE *NOT* interested in collection links here
275  }
276  bool clidMatch = false;
277  if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
278  clidMatch = derivesFromIParticle(clids[i]);
279  } else if (ClassID_traits< CONTAINER >::ID() == clids[i]) {
280  clidMatch = true;
281  }
282  if (clidMatch) {
283  returnVec.push_back( names[i] );
284  }
285  }
286  return returnVec;
287  }
288 
289  template< class CONTAINER >
290  std::vector<std::string> TrigComposite_v1::getObjectCollectionNames() const {
291 
292  std::vector< std::string > returnVec;
293  const std::vector< std::string >& names = linkColNames();
294  const std::vector< uint32_t >& clids = linkColClids();
295 
296  for( size_t i = 0; i < names.size(); ++i ) {
297  if (names[i].find(s_collectionSuffix) == std::string::npos) { // Note: ==
298  continue; // ARE interested in collection links here
299  }
300  bool clidMatch = false;
301  if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
302  clidMatch = derivesFromIParticle(clids[i]);
303  } else if (ClassID_traits< CONTAINER >::ID() == clids[i]) {
304  clidMatch = true;
305  }
306  if (clidMatch) {
307  // Unlike with single links, we expect to find multiple links here. Only add the name once.
308  // Name is mangled in storage, need to un-mangle it before returning it to the user.
309  const std::string unmangledName = names[i].substr(0, names[i].size() - s_collectionSuffix.size());
310  if ( std::none_of(returnVec.begin(), returnVec.end(), [&](const auto& s) {return unmangledName == s;}) ) {
311  returnVec.push_back( unmangledName );
312  }
313  }
314  }
315  return returnVec;
316  }
317 
318  template<class CONTAINER>
319  void TrigComposite_v1::checkTypes(const uint32_t storedCLID, const std::string& name) const {
320  if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
321  if (!derivesFromIParticle(storedCLID)) {
322  throw ExcNotIParticleContainer( "xAOD::TrigComposite::checkTypes: "
323  "Cannot retrieve \"" + name + "\" as an IParticle");
324  }
325  } else if (ClassID_traits< CONTAINER >::ID() != storedCLID) {
326  const std::string typeName = SG::normalizedTypeinfoName( typeid( CONTAINER ) );
327  throw std::runtime_error( "xAOD::TrigComposite::checkTypes: "
328  "Wrong type (" + typeName + ") requested "
329  "for name \"" + name + "\"" );
330  }
331  }
332 
333 } // namespace xAOD
334 
335 #endif // XAODTRIGGER_VERSIONS_TRIGCOMPOSITE_V1_ICC