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