ATLAS Offline Software
Loading...
Searching...
No Matches
A/AthLinks/ElementLink.icc
Go to the documentation of this file.
1// Dear emacs, this is -*- c++ -*-
2/*
3 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
4 */
5#ifndef ATHLINKS_ELEMENTLINK_ICC
6#define ATHLINKS_ELEMENTLINK_ICC
7
8// System include(s):
9#include <stdexcept>
10
11// EDM include(s):
12#include "xAODRootAccessInterfaces/TVirtualEvent.h"
13#include "xAODRootAccessInterfaces/TActiveEvent.h"
14
15////////////////////////////////////////////////////////////////////////////////
16//
17// Implementation of the constructors
18//
19
20template< typename STORABLE >
21ElementLink< STORABLE >::ElementLink()
22 : ElementLinkBase(),
23 m_container( 0 ), m_element( 0 ), m_elementCached( false ),
24 m_event( xAOD::TActiveEvent::event() ) {
25
26}
27
28template< typename STORABLE >
29ElementLink< STORABLE >::ElementLink( xAOD::TVirtualEvent* event )
30 : ElementLinkBase(),
31 m_container( 0 ), m_element( 0 ), m_elementCached( false ),
32 m_event( event ) {
33
34}
35
36template< typename STORABLE >
37ElementLink< STORABLE >::ElementLink( const ID_type& key, index_type index,
38 xAOD::TVirtualEvent* event )
39 : ElementLinkBase( 0, index ),
40 m_container( 0 ), m_element( 0 ), m_elementCached( false ),
41 m_event( event ) {
42
43 // Get the active event if the user didn't specify one explicitly:
44 if( ! m_event ) {
45 m_event = xAOD::TActiveEvent::event();
46 }
47
48 // Translate the id into a hashed key:
49 m_persKey = m_event->getHash( key );
50}
51
52template< typename STORABLE >
53ElementLink< STORABLE >::ElementLink( sgkey_t id, index_type index,
54 xAOD::TVirtualEvent* event )
55 : ElementLinkBase( id, index ),
56 m_container( 0 ), m_element( 0 ), m_elementCached( false ),
57 m_event( event ) {
58
59 // Get the active event if the user didn't specify one explicitly:
60 if( ! m_event ) {
61 m_event = xAOD::TActiveEvent::event();
62 }
63}
64
65template< typename STORABLE >
66ElementLink< STORABLE >::ElementLink( const ID_type& key, index_type index,
67 ElementType element,
68 xAOD::TVirtualEvent* event )
69 : ElementLinkBase( 0, index ),
70 m_container( 0 ), m_element( element ), m_elementCached( true ),
71 m_event( event ) {
72
73 // Get the active event if the user didn't specify one explicitly:
74 if( ! m_event ) {
75 m_event = xAOD::TActiveEvent::event();
76 }
77
78 // Translate the id into a hashed key:
79 m_persKey = m_event->getHash( key );
80}
81
82template< typename STORABLE >
83ElementLink< STORABLE >::ElementLink( sgkey_t id, index_type index,
84 ElementType element,
85 xAOD::TVirtualEvent* event )
86 : ElementLinkBase( id, index ),
87 m_container( 0 ), m_element( element ), m_elementCached( true ),
88 m_event( event ) {
89
90 // Get the active event if the user didn't specify one explicitly:
91 if( ! m_event ) {
92 m_event = xAOD::TActiveEvent::event();
93 }
94}
95
96template< typename STORABLE >
97ElementLink< STORABLE >::ElementLink( BaseConstReference container,
98 index_type index,
99 xAOD::TVirtualEvent* event )
100 : ElementLinkBase( 0, index ),
101 m_container( &container ), m_element( 0 ), m_elementCached( false ),
102 m_event( event ) {
103
104 // Get the active event if the user didn't specify one explicitly:
105 if( ! m_event ) {
106 m_event = xAOD::TActiveEvent::event();
107 }
108
109 // Find the identifier of the container that we received:
110 findIdentifier();
111}
112
113template< typename STORABLE >
114ElementLink< STORABLE >::ElementLink( ElementType element,
115 BaseConstReference container,
116 xAOD::TVirtualEvent* event )
117 : ElementLinkBase(),
118 m_container( &container ), m_element( element ), m_elementCached( true ),
119 m_event( event ) {
120
121 // Get the active event if the user didn't specify one explicitly:
122 if( ! m_event ) {
123 m_event = xAOD::TActiveEvent::event();
124 }
125
126 // Find the identifier of the container that we received:
127 findIdentifier();
128 // Find the index of the specified object within the container:
129 findIndex();
130}
131
132template< typename STORABLE >
133ElementLink< STORABLE >::ElementLink( const ElementLink& parent )
134 : ElementLinkBase( parent ),
135 m_container( parent.m_container ), m_element( parent.m_element ),
136 m_elementCached( parent.m_elementCached ), m_event( parent.m_event ) {
137
138}
139
140template< typename STORABLE >
141inline
142ElementLink< STORABLE >::ElementLink( const ID_type& key, index_type index,
143 const EventContext& )
144 : ElementLink( key, index ) {}
145
146template< typename STORABLE >
147inline
148ElementLink< STORABLE >::ElementLink( sgkey_t id, index_type index,
149 const EventContext& )
150 : ElementLink( id, index ) {}
151
152template< typename STORABLE >
153inline
154ElementLink< STORABLE >::ElementLink( const ID_type& key, index_type index, ElementType element,
155 const EventContext& )
156 : ElementLink( key, index, element ) {}
157
158template< typename STORABLE >
159inline
160ElementLink< STORABLE >::ElementLink( sgkey_t id, index_type index, ElementType element,
161 const EventContext& )
162 : ElementLink( id, index, element ) {}
163
164template< typename STORABLE >
165inline
166ElementLink< STORABLE >::ElementLink( BaseConstReference container, index_type index,
167 const EventContext& )
168 : ElementLink( container, index ) {}
169
170template< typename STORABLE >
171inline
172ElementLink< STORABLE >::ElementLink( ElementType element, BaseConstReference container,
173 const EventContext& )
174 : ElementLink( element, container ) {}
175
176//
177////////////////////////////////////////////////////////////////////////////////
178
179template< typename STORABLE >
180ElementLink< STORABLE >&
181ElementLink< STORABLE >::operator=( const ElementLink< STORABLE >& rhs ) {
182
183 // Copy the contents of the base class:
184 ElementLinkBase::operator=( rhs );
185
186 // Copy the contents of this class:
187 m_container = rhs.m_container;
188 m_element = rhs.m_element;
189 m_elementCached = rhs.m_elementCached;
190 m_event = rhs.m_event;
191
192 // Return this object:
193 return *this;
194}
195
196////////////////////////////////////////////////////////////////////////////////
197//
198// Implementation of the setter functions
199//
200
201/// This function can be used to set up an existing element link to point at
202/// an indexed element of a specific object in memory. The link needs to ask
203/// the event for the ID of the received object, so the function can take a
204/// bit of time.
205///
206/// @param container The container that the link should point to
207/// @param index The index of the element inside the container that the link
208/// needs to point to
209/// @returns A dummy value. Failure is signalled by an exception.
210///
211template< typename STORABLE >
212bool ElementLink< STORABLE >::toIndexedElement( BaseConstReference container,
213 index_type index ) {
214
215 // Remember the specified parameters:
216 m_container = &container;
217 m_persIndex = index;
218
219 // Find the identifier of this object:
220 findIdentifier();
221
222 // The object is no longer cached:
223 m_element = 0;
224 m_elementCached = false;
225
226 return true;
227}
228
229/// This is probably the slowest function of the class. It first needs to look
230/// up the ID of the received container inside the event, and then needs to
231/// find the index of the object within this container.
232///
233/// Avoid using if at all possible!
234///
235/// @param container The container that the link should point to
236/// @param element The element within the container that the link should
237/// point to
238/// @returns A dymmy value. Failure is signalled by an exception.
239///
240template< typename STORABLE >
241bool ElementLink< STORABLE >::toContainedElement( BaseConstReference container,
242 ElementType element ) {
243
244 // Remember the specified parameters:
245 m_container = &container;
246 m_element = element;
247
248 // Find the identifier of this object:
249 findIdentifier();
250 // Find the index of the element inside the object:
251 findIndex();
252
253 // Assume that the object is correctly cached:
254 m_elementCached = true;
255
256 return true;
257}
258
259/// This function can be used to set the link to point to a new element inside
260/// the container that it already points to. The function is slow, as it needs
261/// to find the index of the element inside the container.
262///
263/// Avoid using if at all possible!
264///
265/// @param element The element within the container that the link should
266/// point to
267/// @returns A dymmy value. Failure is signalled by an exception.
268///
269template< typename STORABLE >
270bool ElementLink< STORABLE >::setElement( ElementType element ) {
271
272 // Remember the specified parameter:
273 m_element = element;
274
275 // Find the index of the element inside the object:
276 findIndex();
277
278 // Assume that the object is correctly cached:
279 m_elementCached = true;
280
281 return true;
282}
283
284/// This function tells the object to start using a new container. It should
285/// be used together with the setElement function most of the time. It is
286/// however a slow function, so please avoid it if possible.
287///
288/// @param data The container that the link should point to
289/// @param replace <code>true</code> if the element pointer will be replaced
290/// @returns A dymmy value. Failure is signalled by an exception.
291///
292template< typename STORABLE >
293bool ElementLink< STORABLE >::setStorableObject( BaseConstReference data,
294 bool replace ) {
295
296 // Remember the specified parameter:
297 m_container = &data;
298
299 // Find the identifier of the container:
300 findIdentifier();
301
302 // Do different things based on the second argument:
303 if( replace ) {
304 // Remove the cached element:
305 m_element = 0;
306 m_elementCached = false;
307 m_persKey = 0;
308 } else {
309 // Try to find the cached element inside the container:
310 findIndex();
311 }
312
313 return true;
314}
315
316/// This is probably the most preferred way of setting an existing ElementLink
317/// to point to a new element. It doesn't need to do any costly lookups.
318///
319/// @param key The user-readable key of the container
320/// @param index The index of the element inside its container
321/// @param event An alternative event object to use
322///
323template< typename STORABLE >
324void
325ElementLink< STORABLE >::resetWithKeyAndIndex( const ID_type& key,
326 index_type index,
327 xAOD::TVirtualEvent* event ) {
328
329 // Remember the new event object:
330 m_event = event;
331 if( ! m_event ) {
332 m_event = xAOD::TActiveEvent::event();
333 }
334
335 // Update the persistent variables:
336 setPersKey( m_event->getHash( key ) );
337 setPersIndex( index );
338
339 return;
340}
341
342template< typename STORABLE >
343void
344ElementLink< STORABLE >::resetWithKeyAndIndex( const ID_type& key,
345 index_type index,
346 const EventContext& /*ctx*/) {
347 resetWithKeyAndIndex( key, index );
348}
349
350/// This is the fastest way of setting an existing ElementLink to point to a
351/// new element. It's just a bit more inconvenient than the function receiving
352/// a string identifier for the container.
353///
354/// @param id A hashed identifier for the container
355/// @param index The index of the element inside its container
356/// @param event An alternative event object to use
357///
358template< typename STORABLE >
359void
360ElementLink< STORABLE >::resetWithKeyAndIndex( sgkey_t id,
361 index_type index,
362 xAOD::TVirtualEvent* event ) {
363
364 // Remember the new event object:
365 m_event = event;
366 if( ! m_event ) {
367 m_event = xAOD::TActiveEvent::event();
368 }
369
370 // Update the persistent variables:
371 setPersKey( id );
372 setPersIndex( index );
373
374 return;
375}
376
377template< typename STORABLE >
378void
379ElementLink< STORABLE >::resetWithKeyAndIndex( sgkey_t id,
380 index_type index,
381 const EventContext& /*ctx*/ ) {
382 resetWithKeyAndIndex( id, index );
383}
384
385template< typename STORABLE >
386void ElementLink< STORABLE >::reset() {
387
388 // Reset the persistent variables:
389 setPersKey( 0 );
390 setPersIndex( 0 );
391
392 return;
393}
394
395//
396////////////////////////////////////////////////////////////////////////////////
397
398////////////////////////////////////////////////////////////////////////////////
399//
400// Implementation of the accessor functions and operators
401//
402
403template< typename STORABLE >
404typename ElementLink< STORABLE >::BaseConstPointer
405ElementLink< STORABLE >::getStorableObjectPointer() const {
406
407 // Trigger the retrieval of the container/element:
408 cptr();
409 // Return the pointer, not caring if it's a null pointer or not:
410 return m_container;
411}
412
413template< typename STORABLE >
414typename ElementLink< STORABLE >::BaseConstReference
415ElementLink< STORABLE >::getStorableObjectRef() const {
416
417 // Trigger the retrieval of the container/element:
418 cptr();
419 // Check if a container is now available:
420 if( ! m_container ) {
421 throw std::runtime_error( "ElementLink::getStorableObjectRef "
422 "No container is available" );
423 }
424
425 // Return a reference to the container:
426 return *m_container;
427}
428
429template< typename STORABLE >
430const typename ElementLink< STORABLE >::ID_type&
431ElementLink< STORABLE >::dataID() const {
432
433 return m_event->getName( persKey() );
434}
435
436template< typename STORABLE >
437bool ElementLink< STORABLE >::operator==( const ElementLink& rhs ) const {
438
439 return ( ( key() == rhs.key() ) && ( index() == rhs.index() ) );
440}
441
442template< typename STORABLE >
443bool ElementLink< STORABLE >::operator!=( const ElementLink& rhs ) const {
444
445 return ( ! ( *this == rhs ) );
446}
447
448template< typename STORABLE >
449typename ElementLink< STORABLE >::ElementConstReference
450ElementLink< STORABLE >::operator*() const {
451
452 // Access the pointer:
453 ElementConstPointer ptr = cptr();
454 // Check if it could be retrieved:
455 if( ! ptr ) {
456 throw std::runtime_error( "ElementLink::operator*() "
457 "Element not available" );
458 }
459
460 // Return the reference:
461 return *ptr;
462}
463
464/// This is the only function in the ElementLink code that tries to retrieve
465/// information from the event.
466///
467/// @returns A constant pointer to the element, or a null pointer if
468/// unsuccessful
469///
470template< typename STORABLE >
471typename ElementLink< STORABLE >::ElementConstPointer
472ElementLink< STORABLE >::cptr() const {
473
474 /// Default key, calculated just once:
475 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
476 xAOD::TVirtualEvent::KEY_MASK );
477
478 // If the object is already cached, return right away:
479 if( m_elementCached ) return &m_element;
480 // If we can't retrieve it, sad day for us:
481 if( ( ! m_event ) || ( ! persKey() ) ||
482 ( persKey() == DEFAULT_KEY ) ) return 0;
483
484 // The object should be cached from now on:
485 m_elementCached = true;
486
487 // If the container is cached at least, then things are relatively simple:
488 if( m_container ) {
489 typename STORABLE::size_type index =
490 static_cast< typename STORABLE::size_type >( persIndex() );
491 m_element = ( *m_container )[ index ];
492 return &m_element;
493 }
494
495 // Ask the Event object for the container:
496 if( ! m_event->retrieve( m_container, persKey() ) ) {
497 m_element = 0;
498 m_elementCached = false;
499 return 0;
500 }
501
502 // Get the correct element out of the container:
503 typename STORABLE::size_type index =
504 static_cast< typename STORABLE::size_type >( persIndex() );
505 m_element = ( *m_container )[ index ];
506
507 // Return a pointer to the element:
508 return &m_element;
509}
510
511template< typename STORABLE >
512bool ElementLink< STORABLE >::isValid() const {
513
514 // If we already have the element cached, the answer is simple:
515 if( m_elementCached && m_element ) {
516 return true;
517 }
518
519 /// Default key, calculated just once:
520 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
521 xAOD::TVirtualEvent::KEY_MASK );
522
523 // Start with the simple checks:
524 if( ( ! m_event ) || ( ! persKey() ) ||
525 ( persKey() == DEFAULT_KEY ) ) return false;
526
527 // Check whether the container can be accessed:
528 if( ! m_event->retrieve( m_container, persKey(), true ) ) {
529 return false;
530 }
531
532 // Check that the container is large enough:
533 if( m_container->size() <=
534 static_cast< typename STORABLE::size_type >( persIndex() ) ) {
535 return false;
536 }
537
538 // Apparently things should work well:
539 return true;
540}
541
542//
543////////////////////////////////////////////////////////////////////////////////
544
545template< typename STORABLE >
546bool ElementLink< STORABLE >::toTransient() {
547
548 m_container = 0;
549 m_element = 0;
550 m_elementCached = false;
551
552 return true;
553}
554
555/// This function is used internally to find the hashed identifier for a
556/// container that was given to the ElementLink by reference. It throws an
557/// exception if the object can't be found in the event.
558///
559template< typename STORABLE >
560void ElementLink< STORABLE >::findIdentifier() {
561
562 // Ask the event for the identifier of this object:
563 const sgkey_t key = m_event->getKey( m_container );
564 if( ! key ) {
565 throw std::runtime_error( "ElementLink::findIdentifier: Couldn't find "
566 "the received object in the current event" );
567 }
568
569 // Remember this key:
570 m_persKey = key;
571
572 return;
573}
574
575/// This function is used internally to find the index of a given element inside
576/// the container. It has to do a linear search, so it's quite slow...
577///
578template< typename STORABLE >
579void ElementLink< STORABLE >::findIndex() {
580
581 // Check that we have a valid container:
582 if( ! m_container ) {
583 throw std::runtime_error( "ElementLink::findIndex: No valid container" );
584 }
585
586 // Look for the element insied the container:
587 const_iterator el_itr = m_container->begin();
588 const_iterator el_end = m_container->end();
589 for( index_type i = 0; el_itr != el_end; ++el_itr, ++i ) {
590
591 // Check if this is the element that we're looking for:
592 if( *el_itr != m_element ) continue;
593
594 // If yes, we're finished:
595 m_persIndex = i;
596 return;
597 }
598
599 // If we didn't find the element in the container, that's a problem...
600 throw std::runtime_error( "ElementLink::findIndex: Couldn't find element "
601 "in the current container" );
602
603 return;
604}
605
606template <typename STORABLE>
607bool operator< (const ElementLink<STORABLE> &lhs,
608 const ElementLink<STORABLE> &rhs)
609{
610 return std::make_pair(lhs.persKey(), lhs.index()) < std::make_pair(rhs.persKey(), rhs.index());
611}
612
613template <typename STORABLE>
614bool operator> (const ElementLink<STORABLE> &lhs,
615 const ElementLink<STORABLE> &rhs)
616{
617 return rhs < lhs;
618}
619
620#endif // ATHLINKS_ELEMENTLINK_ICC