ATLAS Offline Software
Loading...
Searching...
No Matches
A/AthLinks/DataLink.icc
Go to the documentation of this file.
1// Dear emacs, this is -*- c++ -*-
2/*
3 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
4 */
5#ifndef ATHLINKS_DATALINK_ICC
6#define ATHLINKS_DATALINK_ICC
7
8// System include(s):
9#include <stdexcept>
10
11// ROOT include(s):
12#include <TError.h>
13
14// EDM include(s):
15#include "xAODRootAccessInterfaces/TVirtualEvent.h"
16#include "xAODRootAccessInterfaces/TActiveEvent.h"
17
18////////////////////////////////////////////////////////////////////////////////
19//
20// Implementation of the different constructors
21//
22
23/// This constructor creates an object that will either return a null pointer
24/// when asked for one, or throw an exception when trying to de-reference it.
25///
26template< typename STORABLE >
27DataLink< STORABLE >::DataLink()
28 : DataLinkBase(), m_object( 0 ), m_event( xAOD::TActiveEvent::event() ) {
29
30}
31
32/// This constructor allows the user to create a null-pointer that uses an
33/// alternative TVirtualEvent object as its store.
34///
35/// @param event Pointer to an alternative TVirtualEvent object
36///
37template< typename STORABLE >
38DataLink< STORABLE >::DataLink( xAOD::TVirtualEvent* event )
39 : DataLinkBase(), m_object( 0 ), m_event( event ) {
40
41}
42
43/// This constructor can be used to create a valid object based on a reference
44/// to an existing object, that's already part of the current event. In case
45/// the object can not be found in the current event, the constructor throws
46/// an exception.
47///
48/// @param data A constant reference to the object that the smart pointer
49/// should point to
50/// @param event Pointer to an alternative TVirtualEvent object
51///
52template< typename STORABLE >
53DataLink< STORABLE >::DataLink( const_reference data,
54 xAOD::TVirtualEvent* event )
55 : DataLinkBase(), m_object( &data ), m_event( event ) {
56
57 // Get the active event if the user didn't specify one explicitly:
58 if( ! m_event ) {
59 m_event = xAOD::TActiveEvent::event();
60 }
61
62 // Find the identifier of the object that we received:
63 findIdentifier();
64}
65
66/// This constructor can be used to create a valid object based on a pointer
67/// to an existing object, that's already part of the current event. In case
68/// the object can not be found in the current event, the constructor throws
69/// an exception.
70///
71/// @param data A constant pointer to the object that the smart pointer
72/// should point to
73/// @param event Pointer to an alternative TVirtualEvent object
74///
75template< typename STORABLE >
76DataLink< STORABLE >::DataLink( const_pointer data, xAOD::TVirtualEvent* event )
77 : DataLinkBase(), m_object( data ), m_event( event ) {
78
79 // Get the active event if the user didn't specify one explicitly:
80 if( ! m_event ) {
81 m_event = xAOD::TActiveEvent::event();
82 }
83
84 // Find the identifier of the object that we received:
85 findIdentifier();
86}
87
88/// This is probably the most convenient version of the constructors.
89/// It receives a string identifier (branch name) for the object that the smart
90/// pointer should reference.
91///
92/// @param id A string identifier for the object to be referenced
93/// @param event Pointer to an alternative TVirtualEvent object
94///
95template< typename STORABLE >
96DataLink< STORABLE >::DataLink( const ID_type& id, xAOD::TVirtualEvent* event )
97 : DataLinkBase(), m_object( 0 ), m_event( event ) {
98
99 // Get the active event if the user didn't specify one explicitly:
100 if( ! m_event ) {
101 m_event = xAOD::TActiveEvent::event();
102 }
103
104 // Translate the id into a hashed key:
105 m_persKey = m_event->getHash( id );
106}
107
108/// This is the most cost-effective of the constructors after the default
109/// one. It relies on the user knowing exactly what hashed key to ask for
110/// for the target object.
111///
112/// @param key A hashed key identifying the object to be referenced
113/// @param event Pointer to an alternative TVirtualEvent object
114///
115template< typename STORABLE >
116DataLink< STORABLE >::DataLink( sgkey_t key, xAOD::TVirtualEvent* event )
117 : DataLinkBase( key ), m_object( 0 ), m_event( event ) {
118
119 // Get the active event if the user didn't specify one explicitly:
120 if( ! m_event ) {
121 m_event = xAOD::TActiveEvent::event();
122 }
123}
124
125/// Simple copy-constructor. It just copies the persistent information
126/// from the base class together with the TVirtualEvent pointer that the parent
127/// class had.
128///
129/// @param parent The parent object to be copied
130///
131template< typename STORABLE >
132template< typename T >
133DataLink< STORABLE >::DataLink( const DataLink< T >& parent )
134 : DataLinkBase( parent ), m_object( 0 ), m_event( parent.m_event ) {
135
136}
137
138//
139////////////////////////////////////////////////////////////////////////////////
140
141////////////////////////////////////////////////////////////////////////////////
142//
143// Implementation of the different setter functions
144//
145
146/// This function should be used to set up the object when your code has a
147/// reference to the target object.
148///
149/// The function will throw an exception if the supplied object can't be found
150/// in the current event.
151///
152/// @param data A reference to the target object
153///
154template< typename STORABLE >
155void DataLink< STORABLE >::toStorableObject( const_reference data ) {
156
157 // Remember the pointer:
158 m_object = &data;
159
160 // Now try to look up the object in the store:
161 findIdentifier();
162
163 return;
164}
165
166/// This function sets up the object to point at the default object of the
167/// template type in the event. It can be useful when only one object of a
168/// given type is available.
169///
170template< typename STORABLE >
171void DataLink< STORABLE >::toDefaultObject() {
172
173 // Reset the cached pointer:
174 m_object = 0;
175
176 // Set a special value for the persistent variable:
177 setPersKey( xAOD::TVirtualEvent::DEFAULT_KEY );
178
179 return;
180}
181
182/// This is one of the more convenient functions. It sets up the smart pointer
183/// using a user-readable string idetifier for the target object.
184///
185/// @param id A string identifier (branch name) for the target object
186///
187template< typename STORABLE >
188void DataLink< STORABLE >::toIdentifiedObject( const ID_type& id ) {
189
190 // Check if we have a valid event:
191 if( ! m_event ) {
192 throw std::runtime_error( "DataLink::toIdentifiedObject: No valid "
193 "TVirtualEvent pointer available (key: " +
194 id + ")" );
195 }
196
197 // Reset the cached pointer:
198 m_object = 0;
199
200 // Set the persistent key using this identifier:
201 m_persKey = m_event->getHash( id );
202
203 return;
204}
205
206/// This function hardly has to do anything. It just sets the received key as
207/// the persistent information for the object, and resets its internals.
208///
209/// @param key The hashed key for the target object
210///
211template< typename STORABLE >
212void DataLink< STORABLE >::toIdentifiedObject( sgkey_t key ) {
213
214 // Reset the cached pointer:
215 m_object = 0;
216
217 // Set the persistent key:
218 m_persKey = key;
219
220 return;
221}
222
223//
224////////////////////////////////////////////////////////////////////////////////
225
226////////////////////////////////////////////////////////////////////////////////
227//
228// Implementation of the different accessor functions
229//
230
231/// This operator can be used to get a constant reference to the object.
232/// In most cases though one should probably use the -> operator instead.
233/// The code throws an exception if the target object is not available.
234///
235/// @returns A constant reference to the target object if available
236///
237template< class STORABLE >
238typename DataLink< STORABLE >::const_reference
239DataLink< STORABLE >::operator*() const {
240
241 // See if we have a valid object:
242 const_pointer ptr = cptr();
243
244 // If not, throw an exception:
245 if( ! ptr ) {
246 throw std::runtime_error( "DataLink::operator*: No valid target for the "
247 "object" );
248 }
249
250 // Return the reference. Notice that we're not using the temporary variable
251 // here...
252 return *m_object;
253}
254
255/// This function is doing most of the heavy lifting. It interacts with the
256/// TVirtualEvent object to deliver a pointer to the target object to the user.
257///
258/// @returns A constant pointer to the target object if available, a
259/// null pointer if not
260///
261template< class STORABLE >
262typename DataLink< STORABLE >::const_pointer
263DataLink< STORABLE >::cptr() const {
264
265 // If the object is already cached, return right away:
266 if( m_object || ( ! m_event ) ) return m_object;
267
268 /// Default key, calculated just once:
269 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
270 xAOD::TVirtualEvent::KEY_MASK );
271
272 // If the key is nonsensical, fail silently:
273 if( ( ! persKey() ) || ( persKey() == DEFAULT_KEY ) ) {
274 return 0;
275 }
276
277 // Ask the event object for the object in question:
278 if( ! m_event->retrieve( m_object, m_persKey ) ) {
279 m_object = 0;
280 }
281
282 // Return what we acquired:
283 return m_object;
284}
285
286template< class STORABLE >
287bool DataLink< STORABLE >::isValid() const {
288
289 // If we have an object already cached, the answer is easy:
290 if( m_object ) {
291 return true;
292 }
293
294 // If there's no event object, we won't be able to retrieve anything:
295 if( ! m_event ) {
296 return false;
297 }
298
299 /// Default key, calculated just once:
300 static const uint32_t DEFAULT_KEY = ( xAOD::TVirtualEvent::DEFAULT_KEY &
301 xAOD::TVirtualEvent::KEY_MASK );
302
303 // Check for non-valid keys:
304 if( ( ! persKey() ) || ( persKey() == DEFAULT_KEY ) ) {
305 return false;
306 }
307
308 // Try retrieving the object:
309 if( ! m_event->retrieve( m_object, m_persKey, true ) ) {
310 return false;
311 }
312
313 // Apparently the link can be de-referenced:
314 return true;
315}
316
317template< typename STORABLE >
318const typename DataLink< STORABLE >::ID_type&
319DataLink< STORABLE >::dataID() const {
320
321 return m_event->getName( persKey() );
322}
323
324//
325////////////////////////////////////////////////////////////////////////////////
326
327/// This function is just here to enable us compiling the same EDM code as
328/// we do offline. We don't actually need to prepare this object for being
329/// written out, it's always in a consistent state.
330///
331/// @returns A dummy value. Just to have the same signature as the offline
332/// function.
333///
334template< class STORABLE >
335bool DataLink< STORABLE >::toPersistent() {
336
337 return true;
338}
339
340/// This function just resets the cached pointer when ROOT streams in a new
341/// object from a TBranch.
342///
343/// @returns A dummy value. Just to have the same signature as the offline
344/// function.
345///
346template< class STORABLE >
347bool DataLink< STORABLE >::toTransient() {
348
349 m_object = 0;
350 return true;
351}
352
353/// This function is used internally to find the hashed identifier for an object
354/// that was given to the DataLink either by reference or pointer. It throws an
355/// exception if the object can't be found in the event.
356///
357template< class STORABLE >
358void DataLink< STORABLE >::findIdentifier() {
359
360 // Ask the event for the identifier of this object:
361 const sgkey_t key = m_event->getKey( m_object );
362 if( ! key ) {
363 Warning( "DataLink::findIdentifier",
364 "Couldn't find the received object in the current event" );
365 }
366
367 // Remember this key:
368 m_persKey = key;
369
370 return;
371}
372
373#endif // ATHLINKS_DATALINK_ICC