1 // Dear emacs, this is -*- c++ -*-
4 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
7 #ifndef XAODTRIGGER_VERSIONS_TRIGCOMPOSITE_V1_ICC
8 #define XAODTRIGGER_VERSIONS_TRIGCOMPOSITE_V1_ICC
15 #include "AthContainers/tools/CurrentEventStore.h"
16 #include "AthContainers/DataVector.h"
17 #include "AthContainers/normalizedTypeinfoName.h"
18 #include "AthContainers/Accessor.h"
19 #include "xAODCore/CLASS_DEF.h"
21 // In "standalone mode" xAOD::IParticleContainer doesn't have a CLID
22 // defined for it. But this code requires one to be set.
24 // The following is incredibly ugly, but this is the best that I could
25 // come up with on short notice. Note that the CLID value is copy-pasted
26 // from the IParticleContainer.h header.
27 #include "xAODBase/IParticleContainer.h"
28 #ifdef XAOD_STANDALONE
29 CLASS_DEF( xAOD::IParticleContainer, 1241842700, 1 )
30 #endif // XAOD_STANDALONE
34 template< typename TYPE >
35 bool TrigComposite_v1::hasDetail( const std::string& name ) const {
37 // Object used to check for the existence of an object:
38 ConstAccessor< TYPE > acc( name );
40 // Use the Accessor object for the check:
41 return acc.isAvailable( *this );
44 template< typename TYPE >
45 bool TrigComposite_v1::setDetail( const std::string& name, const TYPE& value ) {
46 // It should be pretty strange if this should fail:
47 SG::Accessor< TYPE > acc( name );
50 } catch(const std::exception& exc) {
51 std::cerr << "xAOD::TrigComposite_v1::setDetail ERROR Internal logic error found: [" << exc.what() << "]" << std::endl;
58 template< typename TYPE >
59 bool TrigComposite_v1::getDetail( const std::string& name, TYPE& value) const {
60 if( ! hasDetail<TYPE>(name) ) {
63 // Object used to access the auxiliary data:
64 ConstAccessor< TYPE > acc( name );
69 template< typename TYPE >
70 TYPE TrigComposite_v1::getDetail( const std::string& name ) const {
72 if ( getDetail(name, temp) == false )
73 throw std::runtime_error( "xAOD::TrigComposite::getDetail<TYPE>("+name+") encountered missing detail");
77 template< class CONTAINER >
79 TrigComposite_v1::setObjectLink( const std::string& name,
80 const ElementLink< CONTAINER >& link ) {
82 // Check link has valid persistent state, i.e. hash key is not
83 // zero, otherwise attempting to access its string key will seg
84 // fault later, e.g. in remapping.
85 if( link.key() == 0 ) {
86 std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR "
87 << "link has invalid key hash of zero" << std::endl;
91 if( ! link.isValid() ) {
92 std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR "
93 << "link is not valid" << std::endl;
97 // Do different things depending on whether this variable already
99 if( hasObjectLink( name ) ) {
100 // Find the right object:
101 const std::vector< std::string >& names = linkColNames();
102 for( size_t i = 0; i < names.size(); ++i ) {
103 if( names[ i ] != name ) continue;
104 // Extract the information out of the ElementLink:
105 linkColKeysNC()[ i ] = link.key();
106 linkColIndicesNC()[ i ] = link.index();
107 linkColClidsNC()[ i ] = ClassID_traits< CONTAINER >::ID();
111 // Some error happened...
112 std::cerr << "xAOD::TrigComposite_v1::setObjectLink ERROR Internal "
113 << "logic error found" << std::endl;
117 linkColNamesNC().push_back( name );
118 linkColKeysNC().push_back( link.key() );
119 linkColIndicesNC().push_back( link.index() );
120 linkColClidsNC().push_back( ClassID_traits< CONTAINER >::ID() );
126 template< class CONTAINER >
127 ElementLink< CONTAINER >
128 TrigComposite_v1::objectLink( const std::string& name ) const {
130 // Retrieve current store once (would be better to pass EventContext everywhere)
131 auto sg = SG::CurrentEventStore::store();
133 // Find the right object:
134 const std::vector< std::string >& names = linkColNames();
135 for( size_t i = 0; i < names.size(); ++i ) {
136 if( names[ i ] != name ) continue;
137 checkTypes< CONTAINER >(linkColClids()[ i ], name);
138 ElementLink< CONTAINER > link( linkColKeys()[ i ],
139 linkColIndices()[ i ],
142 if (link.isValid()) {
147 return ElementLink< CONTAINER >( linkColKeysRemap()[ i ],
148 linkColIndicesRemap()[ i ],
155 // We didn't find the link. :-(
156 throw std::runtime_error( "xAOD::TrigComposite::objectLink: No link "
157 "name \"" + name + "\" found" );
158 return ElementLink< CONTAINER >();
161 template< class OBJECT >
162 const OBJECT* TrigComposite_v1::object( const std::string& name ) const {
164 // Check if the link exists:
165 if( ! hasObjectLink( name ) ) {
169 // Retrieve current store once (would be better to pass EventContext everywhere)
170 auto sg = SG::CurrentEventStore::store();
173 const std::vector< std::string >& names = linkColNames();
174 for( size_t i = 0; i < names.size(); ++i ) {
175 if( names[ i ] != name ) continue;
176 // Check that it is of the right type:
177 checkTypes< DataVector< OBJECT > >(linkColClids()[ i ], name);
178 // Create a temporary ElementLink:
179 ElementLink< DataVector< OBJECT > > link( linkColKeys()[ i ],
180 linkColIndices()[ i ],
182 if( link.isValid() ) {
187 link = ElementLink< DataVector< OBJECT > >( linkColKeysRemap()[ i ],
188 linkColIndicesRemap()[ i ],
190 if( link.isValid() ) {
198 // There was an internal error. :-(
199 std::cerr << "xAOD::TrigComposite_v1::object ERROR Internal error "
200 << "detected" << std::endl;
204 template< class CONTAINER >
206 TrigComposite_v1::addObjectCollectionLink( const std::string& collectionName,
207 const ElementLink< CONTAINER >& link ) {
209 // No method currently provided to update or check for uniqueness of a link
210 // being added to a container.
212 // Add a new object (unless it would duplicate an existing one):
213 const std::string mangledName = collectionName + s_collectionSuffix;
214 if (!hasObjectLinkExact(mangledName, link.key(), link.index(), ClassID_traits< CONTAINER >::ID())) {
215 linkColNamesNC().push_back( mangledName );
216 linkColKeysNC().push_back( link.key() );
217 linkColIndicesNC().push_back( link.index() );
218 linkColClidsNC().push_back( ClassID_traits< CONTAINER >::ID() );
223 template< class CONTAINER >
225 TrigComposite_v1::addObjectCollectionLinks( const std::string& collectionName,
226 const std::vector<ElementLink< CONTAINER >>& links ) {
228 for (const ElementLink< CONTAINER >& link : links ) {
229 addObjectCollectionLink( collectionName, link );
234 template< class CONTAINER >
235 std::vector<ElementLink< CONTAINER >>
236 TrigComposite_v1::objectCollectionLinks( const std::string& collectionName ) const {
237 std::vector<ElementLink< CONTAINER >> links;
238 const std::string mangledName = collectionName + s_collectionSuffix;
240 // Retrieve current store once (would be better to pass EventContext everywhere)
241 auto sg = SG::CurrentEventStore::store();
243 const std::vector< std::string >& names = linkColNames();
244 for( size_t i = 0; i < names.size(); ++i ) {
245 if( names[ i ] != mangledName ) continue;
246 // Check that it is of the right type:
247 checkTypes< CONTAINER >(linkColClids()[ i ], collectionName);
248 // Construct and add the link:
249 ElementLink< CONTAINER > link(linkColKeys()[ i ],
250 linkColIndices()[ i ],
252 if (link.isValid()) {
253 links.push_back( link );
254 } else if (isRemapped()) {
255 link = ElementLink< CONTAINER >(linkColKeysRemap()[ i ],
256 linkColIndicesRemap()[ i ],
258 links.push_back( link );
260 links.push_back( link );
266 template< class CONTAINER >
267 std::vector<std::string> TrigComposite_v1::getObjectNames() const {
269 std::vector< std::string > returnVec;
270 const std::vector< std::string >& names = linkColNames();
271 const std::vector< uint32_t >& clids = linkColClids();
273 for( size_t i = 0; i < names.size(); ++i ) {
274 if (names[i].find(s_collectionSuffix) != std::string::npos) { //Note: !=
275 continue; // ARE *NOT* interested in collection links here
277 bool clidMatch = false;
278 if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
279 clidMatch = derivesFromIParticle(clids[i]);
280 } else if (ClassID_traits< CONTAINER >::ID() == clids[i]) {
284 returnVec.push_back( names[i] );
290 template< class CONTAINER >
291 std::vector<std::string> TrigComposite_v1::getObjectCollectionNames() const {
293 std::vector< std::string > returnVec;
294 const std::vector< std::string >& names = linkColNames();
295 const std::vector< uint32_t >& clids = linkColClids();
297 for( size_t i = 0; i < names.size(); ++i ) {
298 if (names[i].find(s_collectionSuffix) == std::string::npos) { // Note: ==
299 continue; // ARE interested in collection links here
301 bool clidMatch = false;
302 if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
303 clidMatch = derivesFromIParticle(clids[i]);
304 } else if (ClassID_traits< CONTAINER >::ID() == clids[i]) {
308 // Unlike with single links, we expect to find multiple links here. Only add the name once.
309 // Name is mangled in storage, need to un-mangle it before returning it to the user.
310 const std::string unmangledName = names[i].substr(0, names[i].size() - s_collectionSuffix.size());
311 if ( std::none_of(returnVec.begin(), returnVec.end(), [&](const auto& s) {return unmangledName == s;}) ) {
312 returnVec.push_back( unmangledName );
319 template<class CONTAINER>
320 void TrigComposite_v1::checkTypes(const uint32_t storedCLID, const std::string& name) const {
321 if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
322 if (!derivesFromIParticle(storedCLID)) {
323 throw ExcNotIParticleContainer( "xAOD::TrigComposite::checkTypes: "
324 "Cannot retrieve \"" + name + "\" as an IParticle");
326 } else if (ClassID_traits< CONTAINER >::ID() != storedCLID) {
327 const std::string typeName = SG::normalizedTypeinfoName( typeid( CONTAINER ) );
328 throw std::runtime_error( "xAOD::TrigComposite::checkTypes: "
329 "Wrong type (" + typeName + ") requested "
330 "for name \"" + name + "\"" );
336 #endif // XAODTRIGGER_VERSIONS_TRIGCOMPOSITE_V1_ICC