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