ATLAS Offline Software
NavigationCore.icc
Go to the documentation of this file.
1 // Emacs -*- c++ -*-
2 
3 /*
4  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 
8 #ifndef TRIGNAVIGATION_HLTNAVIGATIONCORE_ICC
9 #define TRIGNAVIGATION_HLTNAVIGATIONCORE_ICC
10 
11 
12 #include "TrigNavigation/Holder.h"
13 #include "TrigNavigation/Holder.icc"
14 #include "CxxUtils/checker_macros.h"
15 #include "CxxUtils/no_sanitize_undefined.h"
16 
17 /*****************************************************************************
18  *
19  * COMPILE TYPE OBJECTS REGISTRATION
20  *
21  *****************************************************************************/
22 #include <type_traits>//remove_pointer, remove_const
23 
24 
25 /////////////////////////////////////////////////////////////////////////////
26 template<class T>
27 __attribute__((__used__))
28 bool HLT::NavigationCore::getFeatures( const TriggerElement* te,
29  std::vector<const T*>& features, const std::string& label,
30  std::map<const T*, std::string>* /*labels*/) const {
31 
32 
33  class_id_type clid = ClassID_traits<T>::ID();
34  ATH_MSG_DEBUG("getFeatures: of clid: " << clid << "(" << ClassID_traits<T>::typeName() << ")"
35  <<" to TE: " << te->getId()
36  << " label: \"" << label << "\"");
37 
38  TriggerElement::FeatureVec features_access_helpers;
39  bool single = false; bool recursively = false;
40  if (!getFeatureAccessors(te, clid, label, single, features_access_helpers, recursively)) {
41  return false;
42  }
43 
44  for(auto& fea : features_access_helpers) {
45  TriggerElement::ObjectIndex objectIndex(fea.getIndex());
46  HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex());
47  const T* obj(0);
48  if ( holder->get(obj, objectIndex) == false ) {
49  ATH_MSG_WARNING("getFeatures: problems while getting objects #" << objectIndex
50  << " from the holder: " << *holder);
51  } else {
52  features.push_back(obj);
53  }
54  }
55  return true;
56 }
57 
58 /////////////////////////////////////////////////////////////////////////////
59 template<class T>
60 __attribute__((__used__))
61 bool HLT::NavigationCore::getFeature NO_SANITIZE_UNDEFINED ( const TriggerElement* te, const T*& feature, const std::string& label, std::string& sourcelabel) const {
62 
63  feature = 0;
64 
65  class_id_type clid = ClassID_traits<T>::ID();
66 
67  ATH_MSG_DEBUG("getFeature: of clid: " << clid << "(" << ClassID_traits<T>::typeName() << ")"
68  <<" to TE: " << te->getId()
69  << " label: \"" << label << "\"");
70 
71  TriggerElement::FeatureVec features_access_helpers;
72  bool single = true; bool recursively = false;
73  if (!getFeatureAccessors(te, clid, label, single, features_access_helpers, recursively, m_unspecifiedTE, sourcelabel)) {
74  return false;
75  }
76  // remove following after testing
77  if ( features_access_helpers.size() > 1 ) {
78  ATH_MSG_WARNING("getFeature: logic error, got: " << features_access_helpers.size() << " features from: getFeatureAccessors");
79  }
80 
81 
82  if ( features_access_helpers.empty() )
83  return true;
84 
85  const TriggerElement::FeatureAccessHelper& fea = features_access_helpers.front();
86  TriggerElement::ObjectIndex objectIndex(fea.getIndex());
87 
88  HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex());
89  if (!holder) {
90  return false;
91  }
92 
93  if ( holder->get(feature, objectIndex) == false ) {
94  ATH_MSG_WARNING("getFeature: problems while getting objects #" << objectIndex
95  << " from the holder: " << *holder);
96  feature = 0;
97  }
98 
99  return true;
100 }
101 
102 template<class T>
103 __attribute__((__used__))
104 bool HLT::NavigationCore::getFeature( const TriggerElement* te,
105  const ConstDataVector<T>*& feature,
106  const std::string& label, std::string& sourcelabel) const {
107  const T* dv = nullptr;
108  if (!getFeature (te, dv, label, sourcelabel))
109  return false;
110 
111  feature = ConstDataVector<T>::fromDataVector (dv);
112  return feature != nullptr;
113 }
114 
115 
116 /////////////////////////////////////////////////////////////////////////////
117 template<class C, class T>
118 __attribute__((__used__))
119 bool HLT::NavigationCore::getFeaturesLinks( const TriggerElement* te, ElementLinkVector<C>& links, const std::string& label) const {
120 
121  class_id_type clid = ClassID_traits<T>::ID();
122 
123  ATH_MSG_DEBUG("getFeaturesLinks: of clid: " << clid << "(" << ClassID_traits<T>::typeName() << ")"
124  << " to TE: " << te->getId()
125  << " label: \"" << label << "\"");
126 
127  TriggerElement::FeatureVec features_access_helpers;
128  bool single = false; bool recursively = false;
129  if (!getFeatureAccessors(te,clid, label, single, features_access_helpers, recursively)) {
130  return false;
131  }
132 
133  for(auto& fea : features_access_helpers) {
134  TriggerElement::ObjectIndex objectIndex(fea.getIndex());
135  HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex());
136 
137  if ( holder->get(links, objectIndex) == false ) {
138  ATH_MSG_WARNING("getFeaturesLinks: problems while getting objects #" << objectIndex
139  << " from the holder: " << *holder);
140  }
141  }
142  return true;
143 }
144 
145 
146 /////////////////////////////////////////////////////////////////////////////
147 template<class T>
148 __attribute__((__used__))
149 bool HLT::NavigationCore::getRecentFeatures( const TriggerElement* te,
150  std::vector<const T*>& features, const std::string& label,
151  std::map<const T*, std::string>* /*labels*/) const {
152 
153  class_id_type clid = ClassID_traits<T>::ID();
154 
155  // start from itself
156  ATH_MSG_DEBUG("getRecentFeatures: looking for CLID: " << clid << "(" << ClassID_traits<T>::typeName() << ")"
157  << " in TE: " << te->getId()
158  << " label: \"" << label << "\"");
159 
160  TriggerElement::FeatureVec features_access_helpers;
161  bool single = false; bool recursively = true;
162 
163  if (!getFeatureAccessors(te, clid, label, single, features_access_helpers, recursively)) {
164  return false;
165  }
166 
167  // type specific code
168  for( auto& fea : features_access_helpers) {
169  TriggerElement::ObjectIndex objectIndex(fea.getIndex());
170  HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex());
171  const T* obj(0);
172  if ( holder->get(obj, objectIndex) == false ) {
173  ATH_MSG_WARNING("getRecentFeatures: problems while getting objects #" << objectIndex
174  << " from the holder: " << *holder);
175  } else {
176  features.push_back(obj);
177  }
178  }
179  return true;
180 }
181 
182 /////////////////////////////////////////////////////////////////////////////
183 template<class T>
184 __attribute__((__used__))
185 bool HLT::NavigationCore::getRecentFeature( const TriggerElement* te,
186  const T*& feature, const std::string& label,
187  const TriggerElement*& source, std::string& sourcelabel ) const {
188 
189  // important! set pointer to NULL to signify nothing was found, it will later be reset to sth else eventually
190  feature = 0;
191 
192  class_id_type clid = ClassID_traits<T>::ID();
193 
194  ATH_MSG_DEBUG("getRecentFeature: looking for CLID: " << ClassID_traits<T>::ID() << "(" << ClassID_traits<T>::typeName() << ")"
195  << " in TE: " << te->getId()
196  << " label: \"" << label << "\"");
197 
198  TriggerElement::FeatureVec features_access_helpers;
199  bool single = true; bool recursively = true;
200 
201  if (!getFeatureAccessors(te, clid, label, single, features_access_helpers, recursively, source, sourcelabel)) {
202  return false;
203  }
204  // remove following after testing
205  if ( features_access_helpers.size() > 1 ) {
206  ATH_MSG_WARNING("getRecentFeature: logic error, got: " << features_access_helpers.size() << " features from: getRecentFeaturesImpl" );
207  }
208 
209  if ( features_access_helpers.empty() )
210  return true;
211 
212  const TriggerElement::FeatureAccessHelper& fea = features_access_helpers.front();
213  TriggerElement::ObjectIndex objectIndex(fea.getIndex());
214  HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex());
215 
216  if ( holder->get(feature, objectIndex) == false ) {
217  ATH_MSG_WARNING("getRecentFeature: problems while getting objects #" << objectIndex
218  << " from the holder: " << *holder);
219  feature = 0;
220  }
221 
222  return true;
223 }
224 
225 /////////////////////////////////////////////////////////////////////////////
226 template<class C, class T>
227 __attribute__((__used__))
228 bool HLT::NavigationCore::getRecentFeaturesLinks( const TriggerElement* te,
229  ElementLinkVector<C>& links, const std::string& label ) const {
230 
231 
232  class_id_type clid = ClassID_traits<T>::ID();
233 
234  ATH_MSG_DEBUG("getRecentFeaturesLinks: looking for CLID: " << ClassID_traits<T>::ID()
235  << "(" << ClassID_traits<T>::typeName() << ")"
236  << " in TE: " << te->getId()
237  << " label: \"" << label << "\"");
238 
239  TriggerElement::FeatureVec features_access_helpers;
240  bool single = false; bool recursively = true;
241 
242  if (!getFeatureAccessors(te, clid, label, single, features_access_helpers, recursively)) {
243  return false;
244  }
245 
246  for(auto& fea : features_access_helpers) {
247  TriggerElement::ObjectIndex objectIndex(fea.getIndex());
248  HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex());
249 
250  if ( holder->get(links, objectIndex) == false ) {
251  ATH_MSG_WARNING("getRecentFeaturesLinks: problems while getting objects #" << objectIndex
252  << " from the holder: " << *holder);
253  }
254  }
255  return true;
256 }
257 
258 //helper struct to get the container type if template argument is datalink or the element type if template arg is ElementLink
259 
260 template<class LinkType>
261 struct link_to_type;
262 
263 template<class CONTAINERTYPE>
264 struct link_to_type<DataLink<CONTAINERTYPE> >{
265  typedef CONTAINERTYPE container_type;
266  typedef typename DataLink<CONTAINERTYPE>::value_type type;
267 };
268 
269 template<class CONTAINERTYPE>
270 struct link_to_type<ElementLink<CONTAINERTYPE> >{
271  typedef CONTAINERTYPE container_type;
272  typedef typename ElementLink<CONTAINERTYPE>::ElementType ptr2constT_type; // is a const T* if T is the feature type
273  typedef typename std::remove_pointer<ptr2constT_type>::type constT_type; // is a const T
274  typedef typename std::remove_const<constT_type>::type type; // is a T
275 };
276 
277 
278 /////////////////////////////////////////////////////////////////////////////
279 template<class LinkType>
280 __attribute__((__used__))
281 bool HLT::NavigationCore::getRecentFeatureDataOrElementLink( const TriggerElement* te, LinkType& link, const std::string& label,
282  const TriggerElement*& source, std::string& sourcelabel) const {
283 
284 
285 
286 
287  typedef typename link_to_type<LinkType>::type T;
288  class_id_type clid = ClassID_traits<T>::ID();
289  ATH_MSG_DEBUG("getRecentFeatureDataOrElementLink: looking for CLID: " << clid << "(" << ClassID_traits<T>::typeName() << ")"
290  << " in TE: " << te->getId()
291  << " label: \"" << label << "\"");
292 
293  TriggerElement::FeatureVec features_access_helpers;
294  bool single = true; bool recursively = true;
295  if (!getFeatureAccessors(te, clid, label, single, features_access_helpers, recursively, source, sourcelabel)) {
296  ATH_MSG_INFO("looking for FAs failed. Returning false! Details CLID: " << ClassID_traits<T>::ID() <<
297  "(" << ClassID_traits<T>::typeName() << ")"
298  << " in TE: " << te->getId() << " label: \"" << label << "\"");
299  return false;
300  }
301 
302  // remove following after testing
303  if ( features_access_helpers.size() > 1 ) {
304  ATH_MSG_WARNING("getRecentFeature: logic error, got: " << features_access_helpers.size() << " features from: getRecentFeaturesImpl" );
305  }
306 
307  if ( features_access_helpers.empty() )
308  return true;
309 
310  const TriggerElement::FeatureAccessHelper& fea = features_access_helpers.front();
311  TriggerElement::ObjectIndex objectIndex(fea.getIndex());
312  HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex());
313 
314  //apparently must use function pointer to get all the types resolved properly
315  typedef typename link_to_type<LinkType>::container_type containertype;
316  bool (HLTNavDetails::Holder<T>::*funcptr) (LinkType&, HLT::TriggerElement::ObjectIndex&) =
317  &HLTNavDetails::Holder<T>::template getWithLink<containertype>;
318 
319  if ( (holder->*funcptr)(link, objectIndex) == false ) {
320  ATH_MSG_WARNING("getRecentFeatureLink: problems while getting objects #" << objectIndex
321  << " from the holder: " << *holder);
322  }
323  return true;
324 }
325 
326 /////////////////////////////////////////////////////////////////////////////
327 template<class C, class T>
328 __attribute__((__used__))
329 bool HLT::NavigationCore::getRecentFeatureLink( const TriggerElement* te,
330  ElementLink<C>& link, const std::string& label,
331  const TriggerElement*& source,
332  std::string& sourcelabel) const {
333 
334 
335  class_id_type clid = ClassID_traits<T>::ID();
336 
337 
338  ATH_MSG_DEBUG("getRecentFeatureLink: looking for CLID: " << clid << "(" << ClassID_traits<T>::typeName() << ")"
339  << " in TE: " << te->getId()
340  << " label: \"" << label << "\"");
341 
342  if( std::is_same<C, T>::value )
343  return false;
344 
345 
346  TriggerElement::FeatureVec features_access_helpers;
347  bool single = true; bool recursively = true;
348 
349  if (!getFeatureAccessors(te, clid, label, single, features_access_helpers, recursively, source, sourcelabel)) {
350  return false;
351  }
352  // remove following after testing
353  if ( features_access_helpers.size() > 1 ) {
354  ATH_MSG_WARNING("getRecentFeature: logic error, got: " << features_access_helpers.size() << " features from: getRecentFeaturesImpl" );
355  }
356 
357  if ( features_access_helpers.empty() )
358  return true;
359 
360  const TriggerElement::FeatureAccessHelper& fea = features_access_helpers.front();
361  TriggerElement::ObjectIndex objectIndex(fea.getIndex());
362  HLTNavDetails::Holder<T>* holder = getHolder<T>(objectIndex.subTypeIndex());
363 
364  ElementLinkVector<C> links;
365  if ( holder->get(links, objectIndex) == false ) {
366  ATH_MSG_WARNING("getRecentFeatureLink: problems while getting objects #" << objectIndex
367  << " from the holder: " << *holder);
368  } else {
369  if ( links.size() != 1 ) {
370  ATH_MSG_WARNING("getRecentFeatureLink: problems while getting objects #" << objectIndex
371  << " from the holder: " << *holder << " links vector has size "
372  << links.size() << " while shoudl have size == 1");
373  return false;
374  } else {
375  link = links.back();
376  }
377  }
378  return true;
379 }
380 
381 
382 /////////////////////////////////////////////////////////////////////////////
383 template<class T>
384 __attribute__((__used__))
385 bool HLT::NavigationCore::getFeaturesInRoI( const TriggerElement* te,
386  std::vector<const T*>& features, const std::string& label,
387  std::map<const T*, std::string>* labels) const {
388  // easy, jump to the RoI (if not RoI node) and loop over all TEs attached to it
389  const TriggerElement* roi(0);
390  if ( TrigNavStructure::isRoINode(te) )
391  roi = te;
392  else if ( te->getRelated(TriggerElement::sameRoIRelation).size() == 1 ) // means we do not support topological TEs here
393  roi = *(te->getRelated(TriggerElement::sameRoIRelation).begin());
394  else
395  return false;
396 
397  bool oneRetStatus = false;
398  bool allRetStatus = false;
399  for ( const TriggerElement* te : roi->getRelated(TriggerElement::sameRoIRelation) ) {
400  oneRetStatus = getFeatures(te, features, label, labels ); // the features will be paked to the end of the vector (see push_back in getFeatures)
401  allRetStatus = allRetStatus || oneRetStatus; // that's OK if at least one call returns some feature
402  }
403  return allRetStatus;
404 }
405 
406 /////////////////////////////////////////////////////////////////////////////
407 template<class C, class T>
408 __attribute__((__used__))
409 bool HLT::NavigationCore::getAllFeatures( ElementLinkVector<C>& features, const std::string& label ) const {
410  std::lock_guard<std::recursive_mutex> lock(getMutex());
411  const TrigHolderStructure& holderstorage = getHolderStorage();
412 
413  CLID clid = ClassID_traits<T>::ID();
414  ATH_MSG_DEBUG("getAllFeatures: of clid: " << clid << "(" << ClassID_traits<T>::typeName() << ")"
415  << " label: \"" << label << "\"");
416 
417  for ( auto& iholder : holderstorage.getHoldersOfClid(clid) ) {
418  if ( label == iholder->label() || label == "" ) {
419  HLTNavDetails::Holder<T>* holder = getHolder<T>(iholder->label(), nextSubTypeIndex(clid, label));
420  ATH_MSG_VERBOSE("getAllFeatures: getting from: " << *holder);
421  if ( holder->get(features) == false ) {
422  ATH_MSG_WARNING("getAllFeatures: failed with the holder of clid: " << clid <<
423  "(" << ClassID_traits<T>::typeName() << ")" << " label: \"" << label << "\"");
424  return false;
425  }
426  }
427  }
428  return true;
429 }
430 
431 
432 /////////////////////////////////////////////////////////////////////////////
433 template<class T>
434 __attribute__((__used__))
435 HLTNavDetails::Holder<T>* HLT::NavigationCore::getHolder NO_SANITIZE_UNDEFINED (const std::string& label, uint16_t suggestedIndex) const {
436 
437  // find object
438  CLID clid = ClassID_traits<T>::ID();
439  ATH_MSG_DEBUG("Getting holder for type: " << clid << " label: " << label);
440 
441  HLTNavDetails::Holder<T>* holder = static_cast<HLTNavDetails::Holder<T>* >(getHolder(clid, label));
442 
443  if ( holder ) {
444  return holder;
445  }
446 
447  // take an appropriate action if this is the first feature of that type#label to be attached/retrieved
448  HLTNavDetails::IHolder* baseholder;
449  if ( createHolder(baseholder, clid, label, suggestedIndex) ) { // create fresh holder
450  ATH_MSG_DEBUG("getHolder: predefined holder got");
451 
452  } else {
453  ATH_MSG_ERROR("getHolder: predefined holder does not exist, load EDM classes for: "
454  << ClassID_traits<T>::typeName() << " CLID " << ClassID_traits<T>::ID());
455  return 0;
456  }
457  holder = static_cast<HLTNavDetails::Holder<T>*>(baseholder);
458 
459  // registerHolder is thread-safe via a mutex:
460  auto nc_this ATLAS_THREAD_SAFE = const_cast<HLT::NavigationCore*>(this);
461  nc_this->registerHolder(holder);
462 
463  return holder;
464 }
465 
466 /////////////////////////////////////////////////////////////////////////////
467 template<class T>
468 __attribute__((__used__))
469 HLTNavDetails::Holder<T>* HLT::NavigationCore::getHolder NO_SANITIZE_UNDEFINED (uint16_t subTypeIndex ) const {
470  // find object
471  CLID clid = ClassID_traits<T>::ID();
472  ATH_MSG_DEBUG("Getting holder for type: " << clid);
473  HLTNavDetails::Holder<T>* holder = static_cast<HLTNavDetails::Holder<T>* >(getHolder(clid, subTypeIndex));
474 
475  return holder;
476 }
477 
478 /////////////////////////////////////////////////////////////////////////////
479 // 2012-09-14 new stuff for composite obejcts
480 
481 //#include "TrigNavigation/NavigationInit.h"
482 
483 #include <stdlib.h>
484 #include <cxxabi.h>
485 
486 namespace HLT{
487 
488  template<class T, class C, bool get_by_contianer, bool get_by_object>
489  struct get{};
490 
491  template<class T, class C>
492  struct get< T, C, false, false>{
493  static const T* do_it(const TrigFeatureLink&, const HLT::NavigationCore* ){
494  return 0; // here compile time error shoudl be generated
495  }
496  };
497 
498  template<class T, class C>
499  struct get< T, C, false, true>{
500  static const T* do_it(const TrigFeatureLink&fl, const HLT::NavigationCore* nav){
501  HLTNavDetails::Holder<T>* holder = nav->getHolder<T>(fl.subTypeIndex());
502  //std::cerr << " Holder acquired " << __LINE__ << std::endl;
503  const T* ptr(0);
504  holder->get(ptr, HLT::TriggerElement::ObjectIndex(fl.subTypeIndex(), fl.index(), fl.index()+1));
505  // std::cerr << " object retrieved " << __LINE__ << std::endl;
506  return ptr;
507  }
508 
509  };
510 
511  template<class T, class C>
512  struct get< T, C, true, false>{
513  static const T* do_it(const TrigFeatureLink&fl, const HLT::NavigationCore* nav){
514  HLTNavDetails::Holder<C>* holder = const_cast<HLT::NavigationCore*>(nav)->getHolder<C>(fl.subTypeIndex());
515  //std::cerr << " Holder acquired " << __LINE__ << " " << fl.clid() << " " << fl.subTypeIndex() << " " << holder << " " << ClassID_traits<C>::ID() << std::endl;
516  const C* ptr(0);
517  holder->get(ptr, HLT::TriggerElement::ObjectIndex(fl.subTypeIndex(), fl.index(), fl.index()+1));
518  //std::cerr << " object retrieved " << __LINE__ << std::endl;
519  if ( ptr and ptr->size() == 1) {
520  return ptr->at(0);
521  }
522  return 0;
523  }
524  };
525 
526 
527  template<class T, class C>
528  struct get< T, C, true, true> {
529  static const T* do_it(const TrigFeatureLink&fl, const HLT::NavigationCore* nav){
530  if ( fl.clid() == ClassID_traits<C>::ID() ) {
531  return get<T,C, true, false>::do_it(fl, nav);
532  } else if ( fl.clid() == ClassID_traits<T>::ID() ) {
533  return get<T,C, false, true>::do_it(fl, nav);
534  }
535  return 0;
536  }
537  };
538 }
539 
540 template<class T>
541 __attribute__((__used__))
542 const T* HLT::NavigationCore::featureLink2Object( const TrigFeatureLink& fl) const {
543  if (! fl.isValid())
544  return (const T*)0;
545 
546  typedef typename Object2Features<T>::type list_of_possible_features;
547  typedef typename Object2Container<T>::type container;
548 
549  // std::cerr << " in the list " << HLT::tool::rtti_real_name(typeid(list_of_possible_features).name()) << std::endl;
550  // std::cerr << " container " << HLT::tool::rtti_real_name(typeid(container).name()) << std::endl;
551  // std::cerr << " has T " << list_of_possible_features::template has<T>::result << std::endl;
552  // std::cerr << " has container " << list_of_possible_features::template has<container>::result << std::endl;
553 
554  const T* ptr = HLT::get<T, container,
555  list_of_possible_features::template has<container>::result,
556  list_of_possible_features::template has<T>::result>::do_it(fl, this);
557 
558  return ptr;
559 
560 }
561 
562 
563 template<class T>
564 __attribute__((__used__))
565 TrigFeatureLink HLT::NavigationCore::object2FeatureLink(const TriggerElement* te, const std::string& label,
566  const T* obj) const {
567 
568  //typedef typename Features2Container<T>::type Container;
569  if ( obj == 0 )
570  return TrigFeatureLink();
571  TriggerElement::FeatureVec features_access_helpers;
572  std::string sourcelabel;
573  if ( getFeatureAccessors(te, ClassID_traits<T>::ID(), label, true, features_access_helpers, true, m_unspecifiedTE, sourcelabel ) == false ) {
574  return TrigFeatureLink();
575  }
576 
577  // remove following after testing
578  if ( features_access_helpers.size() > 1 ) {
579  ATH_MSG_WARNING("getFeature: logic error, got: " << features_access_helpers.size() << " features from: getFeatureAccessors" );
580  }
581 
582  if ( features_access_helpers.empty() )
583  return TrigFeatureLink();
584 
585  const TriggerElement::ObjectIndex& oindex = features_access_helpers.at(0).getIndex();
586  return TrigFeatureLink(ClassID_traits<T>::ID(), oindex.subTypeIndex(), oindex.objectsBegin());
587 
588 }
589 
590 template<class C>
591 __attribute__((__used__))
592 TrigFeatureLink HLT::NavigationCore::object2FeatureLink(const TriggerElement* te, const std::string& label,
593  const typename Container2Object<C>::type* obj,
594  const C* container) const {
595 
596  TriggerElement::FeatureVec features_access_helpers;
597  std::string sourcelabel;
598  if ( getFeatureAccessors(te, ClassID_traits<C>::ID(), label, true, features_access_helpers, true, m_unspecifiedTE, sourcelabel ) == false ) {
599  return TrigFeatureLink();
600  }
601  // remove following after testing
602  if ( features_access_helpers.size() > 1 ) {
603  ATH_MSG_WARNING("getFeature: logic error, got: " << features_access_helpers.size() << " features from: getFeatureAccessors" );
604  }
605 
606  if ( features_access_helpers.empty() )
607  return TrigFeatureLink();
608 
609  const TriggerElement::ObjectIndex& oindex = features_access_helpers.at(0).getIndex();
610  typename C::const_iterator lookup = std::find(container->begin(), container->end(),obj);
611  if ( lookup == container->end() )
612  return TrigFeatureLink();
613 
614  const unsigned offset = lookup - container->begin();
615  return TrigFeatureLink(ClassID_traits<C>::ID(), oindex.subTypeIndex(), oindex.objectsBegin()+offset);
616 
617 }
618 
619 
620 #endif