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-2024 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  if( ! hasDetail<TYPE>(name) ) {
61  return false;
62  }
63  // Object used to access the auxiliary data:
64  ConstAccessor< TYPE > acc( name );
65  value = acc( *this );
66  return true;
67  }
68 
69  template< typename TYPE >
70  TYPE TrigComposite_v1::getDetail( const std::string& name ) const {
71  TYPE temp;
72  if ( getDetail(name, temp) == false )
73  throw std::runtime_error( "xAOD::TrigComposite::getDetail<TYPE>("+name+") encountered missing detail");
74  return temp; // RVO
75  }
76 
77  template< class CONTAINER >
78  bool
79  TrigComposite_v1::setObjectLink( const std::string& name,
80  const ElementLink< CONTAINER >& link ) {
81 
82  // Check link has valid persistent state, i.e. hash key is not
83  // zero, otherwise attempting to access its string key will seg
84  // fault later, e.g. in remapping.
85  if( link.key() == 0 ) {
86  std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR "
87  << "link has invalid key hash of zero" << std::endl;
88  return false;
89  }
90 
91  if( ! link.isValid() ) {
92  std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR "
93  << "link is not valid" << std::endl;
94  return false;
95  }
96 
97  // Do different things depending on whether this variable already
98  // exists or not:
99  if( hasObjectLink( name ) ) {
100  // Find the right object:
101  const std::vector< std::string >& names = linkColNames();
102  for( size_t i = 0; i < names.size(); ++i ) {
103  if( names[ i ] != name ) continue;
104  // Extract the information out of the ElementLink:
105  linkColKeysNC()[ i ] = link.key();
106  linkColIndicesNC()[ i ] = link.index();
107  linkColClidsNC()[ i ] = ClassID_traits< CONTAINER >::ID();
108  // We're done:
109  return true;
110  }
111  // Some error happened...
112  std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR Internal "
113  << "logic error found" << std::endl;
114  return false;
115  } else {
116  // Add a new object:
117  linkColNamesNC().push_back( name );
118  linkColKeysNC().push_back( link.key() );
119  linkColIndicesNC().push_back( link.index() );
120  linkColClidsNC().push_back( ClassID_traits< CONTAINER >::ID() );
121  // And we're done:
122  return true;
123  }
124  }
125 
126  template< class CONTAINER >
127  ElementLink< CONTAINER >
128  TrigComposite_v1::objectLink( const std::string& name ) const {
129 
130  // Retrieve current store once (would be better to pass EventContext everywhere)
131  auto sg = SG::CurrentEventStore::store();
132 
133  // Find the right object:
134  const std::vector< std::string >& names = linkColNames();
135  for( size_t i = 0; i < names.size(); ++i ) {
136  if( names[ i ] != name ) continue;
137  checkTypes< CONTAINER >(linkColClids()[ i ], name);
138  ElementLink< CONTAINER > link( linkColKeys()[ i ],
139  linkColIndices()[ i ],
140  sg );
141 
142  if (link.isValid()) {
143  return link;
144  }
145 
146  if (isRemapped()) {
147  return ElementLink< CONTAINER >( linkColKeysRemap()[ i ],
148  linkColIndicesRemap()[ i ],
149  sg );
150  }
151 
152  return link;
153  }
154 
155  // We didn't find the link. :-(
156  throw std::runtime_error( "xAOD::TrigComposite::objectLink: No link "
157  "name \"" + name + "\" found" );
158  return ElementLink< CONTAINER >();
159  }
160 
161  template< class OBJECT >
162  const OBJECT* TrigComposite_v1::object( const std::string& name ) const {
163 
164  // Check if the link exists:
165  if( ! hasObjectLink( name ) ) {
166  return nullptr;
167  }
168 
169  // Retrieve current store once (would be better to pass EventContext everywhere)
170  auto sg = SG::CurrentEventStore::store();
171 
172  // Now look for it:
173  const std::vector< std::string >& names = linkColNames();
174  for( size_t i = 0; i < names.size(); ++i ) {
175  if( names[ i ] != name ) continue;
176  // Check that it is of the right type:
177  checkTypes< DataVector< OBJECT > >(linkColClids()[ i ], name);
178  // Create a temporary ElementLink:
179  ElementLink< DataVector< OBJECT > > link( linkColKeys()[ i ],
180  linkColIndices()[ i ],
181  sg );
182  if( link.isValid() ) {
183  return *link;
184  }
185 
186  if (isRemapped()) {
187  link = ElementLink< DataVector< OBJECT > >( linkColKeysRemap()[ i ],
188  linkColIndicesRemap()[ i ],
189  sg );
190  if( link.isValid() ) {
191  return *link;
192  }
193  }
194 
195  return nullptr;
196  }
197 
198  // There was an internal error. :-(
199  std::cerr << "xAOD::TrigComposite_v1::object ERROR Internal error "
200  << "detected" << std::endl;
201  return nullptr;
202  }
203 
204  template< class CONTAINER >
205  bool
206  TrigComposite_v1::addObjectCollectionLink( const std::string& collectionName,
207  const ElementLink< CONTAINER >& link ) {
208 
209  // No method currently provided to update or check for uniqueness of a link
210  // being added to a container.
211 
212  // Add a new object (unless it would duplicate an existing one):
213  const std::string mangledName = collectionName + s_collectionSuffix;
214  if (!hasObjectLinkExact(mangledName, link.key(), link.index(), ClassID_traits< CONTAINER >::ID())) {
215  linkColNamesNC().push_back( mangledName );
216  linkColKeysNC().push_back( link.key() );
217  linkColIndicesNC().push_back( link.index() );
218  linkColClidsNC().push_back( ClassID_traits< CONTAINER >::ID() );
219  }
220  return true;
221  }
222 
223  template< class CONTAINER >
224  bool
225  TrigComposite_v1::addObjectCollectionLinks( const std::string& collectionName,
226  const std::vector<ElementLink< CONTAINER >>& links ) {
227  // Add all links
228  for (const ElementLink< CONTAINER >& link : links ) {
229  addObjectCollectionLink( collectionName, link );
230  }
231  return true;
232  }
233 
234  template< class CONTAINER >
235  std::vector<ElementLink< CONTAINER >>
236  TrigComposite_v1::objectCollectionLinks( const std::string& collectionName ) const {
237  std::vector<ElementLink< CONTAINER >> links;
238  const std::string mangledName = collectionName + s_collectionSuffix;
239 
240  // Retrieve current store once (would be better to pass EventContext everywhere)
241  auto sg = SG::CurrentEventStore::store();
242 
243  const std::vector< std::string >& names = linkColNames();
244  for( size_t i = 0; i < names.size(); ++i ) {
245  if( names[ i ] != mangledName ) continue;
246  // Check that it is of the right type:
247  checkTypes< CONTAINER >(linkColClids()[ i ], collectionName);
248  // Construct and add the link:
249  ElementLink< CONTAINER > link(linkColKeys()[ i ],
250  linkColIndices()[ i ],
251  sg);
252  if (link.isValid()) {
253  links.push_back( link );
254  } else if (isRemapped()) {
255  link = ElementLink< CONTAINER >(linkColKeysRemap()[ i ],
256  linkColIndicesRemap()[ i ],
257  sg);
258  links.push_back( link );
259  } else {
260  links.push_back( link );
261  }
262  }
263  return links;
264  }
265 
266  template< class CONTAINER >
267  std::vector<std::string> TrigComposite_v1::getObjectNames() const {
268 
269  std::vector< std::string > returnVec;
270  const std::vector< std::string >& names = linkColNames();
271  const std::vector< uint32_t >& clids = linkColClids();
272 
273  for( size_t i = 0; i < names.size(); ++i ) {
274  if (names[i].find(s_collectionSuffix) != std::string::npos) { //Note: !=
275  continue; // ARE *NOT* interested in collection links here
276  }
277  bool clidMatch = false;
278  if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
279  clidMatch = derivesFromIParticle(clids[i]);
280  } else if (ClassID_traits< CONTAINER >::ID() == clids[i]) {
281  clidMatch = true;
282  }
283  if (clidMatch) {
284  returnVec.push_back( names[i] );
285  }
286  }
287  return returnVec;
288  }
289 
290  template< class CONTAINER >
291  std::vector<std::string> TrigComposite_v1::getObjectCollectionNames() const {
292 
293  std::vector< std::string > returnVec;
294  const std::vector< std::string >& names = linkColNames();
295  const std::vector< uint32_t >& clids = linkColClids();
296 
297  for( size_t i = 0; i < names.size(); ++i ) {
298  if (names[i].find(s_collectionSuffix) == std::string::npos) { // Note: ==
299  continue; // ARE interested in collection links here
300  }
301  bool clidMatch = false;
302  if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
303  clidMatch = derivesFromIParticle(clids[i]);
304  } else if (ClassID_traits< CONTAINER >::ID() == clids[i]) {
305  clidMatch = true;
306  }
307  if (clidMatch) {
308  // Unlike with single links, we expect to find multiple links here. Only add the name once.
309  // Name is mangled in storage, need to un-mangle it before returning it to the user.
310  const std::string unmangledName = names[i].substr(0, names[i].size() - s_collectionSuffix.size());
311  if ( std::none_of(returnVec.begin(), returnVec.end(), [&](const auto& s) {return unmangledName == s;}) ) {
312  returnVec.push_back( unmangledName );
313  }
314  }
315  }
316  return returnVec;
317  }
318 
319  template<class CONTAINER>
320  void TrigComposite_v1::checkTypes(const uint32_t storedCLID, const std::string& name) const {
321  if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
322  if (!derivesFromIParticle(storedCLID)) {
323  throw ExcNotIParticleContainer( "xAOD::TrigComposite::checkTypes: "
324  "Cannot retrieve \"" + name + "\" as an IParticle");
325  }
326  } else if (ClassID_traits< CONTAINER >::ID() != storedCLID) {
327  const std::string typeName = SG::normalizedTypeinfoName( typeid( CONTAINER ) );
328  throw std::runtime_error( "xAOD::TrigComposite::checkTypes: "
329  "Wrong type (" + typeName + ") requested "
330  "for name \"" + name + "\"" );
331  }
332  }
333 
334 } // namespace xAOD
335 
336 #endif // XAODTRIGGER_VERSIONS_TRIGCOMPOSITE_V1_ICC