ATLAS Offline Software
TPConverter.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "GaudiKernel/MsgStream.h"
6 
7 #include <stdexcept>
8 #include <memory>
9 
10 
11 //--------------------------------------------------------------------
12 /*
13  Default implementation of the 2 methods that create new objects:
14  createTransient() and createPersistent()
15  The 2 remaining methods persToTrans() and transToPers() do not have
16  default implementations, they needs to be supplied by the user-defined
17  superclass
18 */
19 
20 template< class TRANS_BASE, class TRANS, class PERS >
21 PERS* TPAbstractPolyCnvBase<TRANS_BASE, TRANS, PERS>::
22 createPersistent(const TRANS* transObj, MsgStream &log) {
23  std::unique_ptr<PERS> pers(new PERS());
24  transToPers(transObj, pers.get(), log);
25  return(pers.release());
26 }
27 
28 
29 template< class TRANS_BASE, class TRANS, class PERS >
30 PERS* TPAbstractPolyCnvBase<TRANS_BASE, TRANS, PERS>::
31 createPersistentWithKey(const TRANS* transObj, const std::string& key, MsgStream &log) {
32  std::unique_ptr<PERS> pers(new PERS());
33  transToPersWithKey(transObj, pers.get(), key, log);
34  return(pers.release());
35 }
36 
37 
38 template< class TRANS_BASE, class TRANS, class PERS >
39 TPObjRef
40 TPAbstractPolyCnvBase<TRANS_BASE, TRANS, PERS>::
41 toPersistentWithKey_impl( const TRANS *trans,
42  const std::string& key,
43  MsgStream &log )
44 {
45  // make sure there is a storage object
46  if( !this->topConverter()->hasTLPersObject() ) {
47  this->topConverter()->createTLPersObject();
48  }
49  // make a new space in the storage vector
50  size_t size = m_pStorage->size();
51  // cppcheck-suppress uninitvar
52  m_pStorage->resize( size+1 );
53 
54  if( m_recursive ) {
55  // for recursive calls use temporary persistent object
56  // as the vector storage may be reallocated in a recursive invocation
57  PERS tmp_pers;
58  transToPersWithKey( trans, &tmp_pers, key, log);
59  // do NOT use back() here (the vector has already grown)
60  m_pStorage->operator[]( size ) = tmp_pers;
61  } else {
62  if( m_curRecLevel > 0 && !m_ignoreRecursion) {
63  throw std::runtime_error(
64  std::string("T/P converter: ") + typeid(*this).name()
65  + " called recursively! -> enable the recursive flag" );
66  }
67  m_curRecLevel++;
68  transToPersWithKey( trans, &m_pStorage->back(), key, log);
69  m_curRecLevel--;
70  }
71  return TPObjRef( this->m_pStorageTID, size );
72 }
73 namespace EventContainers{
74 class IdentifiableContainerBase;
75 }
76 class IdentifiableValueContainerBase;
77 template< class TRANS_BASE, class TRANS, class PERS >
78 TRANS* TPPolyCnvBase<TRANS_BASE, TRANS, PERS>::
79 createTransient ([[maybe_unused]] const PERS* persObj, MsgStream &log)
80 {
81  if constexpr(std::is_base_of< EventContainers::IdentifiableContainerBase, TRANS>::value && !std::is_default_constructible<TRANS>::value) {
82  log << "IdentifiableContainerBase is not compatable with createTransient" << std::endl;
83  return nullptr;
84  }else if constexpr(std::is_base_of< IdentifiableValueContainerBase, TRANS>::value && !std::is_default_constructible<TRANS>::value){
85  log << "IdentifiableValueContainerBase is not compatable with createTransient" << std::endl;
86  return nullptr;
87  }
88  else{
89  // this is by default equivalent to 'new TRANS()'
90  std::unique_ptr<TRANS> trans = std::make_unique<TRANS>();
91 
92  this->persToTrans(persObj, trans.get(), log);
93  return( trans.release() );
94  }
95 }
96 
97 template< class TRANS_BASE, class TRANS, class PERS >
98 TRANS* TPPolyCnvBase<TRANS_BASE, TRANS, PERS>::
99 createTransientWithKey ([[maybe_unused]] const PERS* persObj,
100  const std::string& key,
101  MsgStream& log)
102 {
103  if constexpr(std::is_base_of< EventContainers::IdentifiableContainerBase, TRANS>::value && !std::is_default_constructible<TRANS>::value) {
104  log << "IdentifiableContainerBase is not compatable with createTransient" << std::endl;
105  return nullptr;
106  }else if constexpr(std::is_base_of< IdentifiableValueContainerBase, TRANS>::value && !std::is_default_constructible<TRANS>::value){
107  log << "IdentifiableValueContainerBase is not compatable with createTransient" << std::endl;
108  return nullptr;
109  }
110  else{
111  // this is by default equivalent to 'new TRANS()'
112  std::unique_ptr<TRANS> trans = std::make_unique<TRANS>();
113 
114  this->persToTransWithKey(persObj, trans.get(), key, log);
115  return( trans.release() );
116  }
117 }
118 
119 
120 template< class TRANS, class PERS >
121 TRANS* TPConverterConstBase<TRANS, PERS>::createTransientConst
122  (const PERS* persObj, MsgStream& log) const
123 {
124  if constexpr(std::is_base_of< EventContainers::IdentifiableContainerBase, TRANS>::value && !std::is_default_constructible<TRANS>::value) {
125  log << "IdentifiableContainerBase is not compatable with createTransient" << std::endl;
126  return nullptr;
127  }else if constexpr(std::is_base_of< IdentifiableValueContainerBase, TRANS>::value && !std::is_default_constructible<TRANS>::value){
128  log << "IdentifiableValueContainerBase is not compatable with createTransient" << std::endl;
129  return nullptr;
130  }
131  else{
132  // this is by default equivalent to 'new TRANS()'
133  std::unique_ptr<TRANS> trans = std::make_unique<TRANS>();
134 
135  this->persToTrans(persObj, trans.get(), log);
136  return( trans.release() );
137  }
138 }
139 
140 
141 template< class TRANS, class PERS >
142 PERS* TPConverterConstBase<TRANS, PERS>::createPersistentConst
143  (const TRANS* transObj, MsgStream& log) const
144 {
145  std::unique_ptr<PERS> pers(new PERS());
146  transToPers(transObj, pers.get(), log);
147  return(pers.release());
148 }
149 
150 
151 //--------------------------------------------------------------------
152 /*
153  persToTrans() and transToPers() implementation for a converter between
154  transient vector of T* (like DataVector<T>) and persistent vector<T>
155 */
156 template<class TRANS, class PERS, class CONV>
157 void TPCnvVector<TRANS, PERS, CONV>::persToTrans(const PERS* persVect,
158  TRANS* transVect,
159  MsgStream &log)
160 {
161  typename PERS::const_iterator it;
162  transVect->clear();
163  transVect->reserve(persVect->size());
164  for (it = persVect->begin(); it != persVect->end(); ++it) {
165  transVect->push_back( m_elementCnv.createTransient(&(*it), log) );
166  }
167 }
168 
169 template<class TRANS, class PERS, class CONV>
170 void TPCnvVector<TRANS, PERS, CONV>::transToPers(const TRANS* transVect,
171  PERS* persVect,
172  MsgStream &log) {
173  size_t size = transVect->size();
174  persVect->resize(size);
175  // convert vector entries one by one
176  typename TRANS::const_iterator it = transVect->begin();
177  typename PERS::iterator pit = persVect->begin();
178  while(size) {
179  m_elementCnv.transToPers( *it, &(*pit), log );
180  ++pit; ++it; --size;
181  }
182 }
183 
184 
185 template<class TRANS, class PERS, class CONV>
186 void TPCnvVectorConst<TRANS, PERS, CONV>::persToTrans(const PERS* persVect,
187  TRANS* transVect,
188  MsgStream &log) const {
189  CONV element_cnv;
190  typename PERS::const_iterator it;
191  transVect->clear();
192  transVect->reserve(persVect->size());
193  for (it = persVect->begin(); it != persVect->end(); ++it) {
194  transVect->push_back(element_cnv.createTransient(&(*it), log));
195  }
196 }
197 
198 template<class TRANS, class PERS, class CONV>
199 void TPCnvVectorConst<TRANS, PERS, CONV>::transToPers(const TRANS* transVect,
200  PERS* persVect,
201  MsgStream &log) const {
202  size_t size = transVect->size();
203  persVect->resize(size);
204  // convert vector entries one by one
205  CONV element_cnv;
206  typename TRANS::const_iterator it = transVect->begin();
207  typename PERS::iterator pit = persVect->begin();
208  while(size) {
209  element_cnv.transToPers( *it, &(*pit), log );
210  ++pit; ++it; --size;
211  }
212 }
213 
214 
215 
216 /*
217  persToTrans() and transToPers() implementation for a converter between
218  transient vector of T and persistent vector<T>
219 */
220 template<class TRANS, class PERS, class CONV>
221 void TPCnvStdVector<TRANS, PERS, CONV>::persToTrans(const PERS* persVect,
222  TRANS* transVect,
223  MsgStream &log)
224 {
225  CONV element_cnv;
226  size_t i = persVect->size();
227  transVect->resize( i );
228  typename PERS::const_iterator pit = persVect->begin();
229  typename TRANS::iterator it = transVect->begin();
230  while(i) {
231  element_cnv.persToTrans( &(*pit), &(*it), log );
232  ++it; ++pit; --i;
233  }
234 }
235 
236 template<class TRANS, class PERS, class CONV>
237 void TPCnvStdVector<TRANS, PERS, CONV>::transToPers(const TRANS* transVect,
238  PERS* persVect,
239  MsgStream &log)
240 {
241  CONV element_cnv;
242  size_t i = transVect->size();
243  persVect->resize( i );
244  typename TRANS::const_iterator it = transVect->begin();
245  typename PERS::iterator pit = persVect->begin();
246  while(i) {
247  element_cnv.transToPers( &(*it), &(*pit), log );
248  ++pit; ++it; --i;
249  }
250 }
251 
252 
253 template<class TRANS, class PERS, class CONV>
254 void TPCnvStdVectorConst<TRANS, PERS, CONV>::persToTrans(const PERS* persVect,
255  TRANS* transVect,
256  MsgStream &log) const
257 {
258  CONV element_cnv;
259  size_t i = persVect->size();
260  transVect->resize( i );
261  typename PERS::const_iterator pit = persVect->begin();
262  typename TRANS::iterator it = transVect->begin();
263  while(i) {
264  element_cnv.persToTrans( &(*pit), &(*it), log );
265  ++it; ++pit; --i;
266  }
267 }
268 
269 template<class TRANS, class PERS, class CONV>
270 void TPCnvStdVectorConst<TRANS, PERS, CONV>::transToPers(const TRANS* transVect,
271  PERS* persVect,
272  MsgStream &log) const
273 {
274  CONV element_cnv;
275  size_t i = transVect->size();
276  persVect->resize( i );
277  typename TRANS::const_iterator it = transVect->begin();
278  typename PERS::iterator pit = persVect->begin();
279  while(i) {
280  element_cnv.transToPers( &(*it), &(*pit), log );
281  ++pit; ++it; --i;
282  }
283 }
284 
285 //--------------------------------------------------------------------
286 /*
287  persToTrans() and transToPers() implementation for a converter between
288  transient AtlasHitsVector of T* and persistent vector<T>
289 */
290 template<class TRANS, class PERS, class CONV>
291 void T_AtlasHitsVectorCnv<TRANS, PERS, CONV>::persToTrans(const PERS* persCont,
292  TRANS* transCont,
293  MsgStream &log) {
294  CONV element_cnv;
295  typename TRANS::iterator it;
296  typename PERS::const_iterator ip;
297  const typename PERS::HitVector& pvec = persCont->getVector();
298  transCont->clear();
299  transCont->resize( pvec.size() );
300  for (it=transCont->begin(), ip = pvec.begin(); ip != pvec.end(); ++ip, ++it) {
301  element_cnv.persToTrans( &*ip, &*it, log );
302  }
303  transCont->setName(persCont->name() );
304 }
305 
306 template<class TRANS, class PERS, class CONV>
307 void T_AtlasHitsVectorCnv<TRANS, PERS, CONV>::transToPers(const TRANS* transCont,
308  PERS* persCont,
309  MsgStream &log) {
310  size_t size = transCont->size();
311  typename PERS::HitVector& pvec = persCont->m_cont;
312  pvec.resize(size);
313  // convert vector entries one by one
314  CONV element_cnv;
315  typename TRANS::const_iterator it = transCont->begin();
316  typename PERS::iterator pit = pvec.begin();
317  while(size) {
318  element_cnv.transToPers( &(*it), &(*pit), log );
319  ++it; ++pit; --size;
320  }
321  persCont->m_name = transCont->Name();
322 }
323 
324 
325 //--------------------------------------------------------------------
326 /*
327  persToTrans() and transToPers() implementation for a converter between
328  transient AthenaHitsVector of T* and persistent vector<T>
329 */
330 template<class TRANS, class PERS, class CONV>
331 void T_AthenaHitsVectorCnv<TRANS, PERS, CONV>::persToTrans(const PERS* persCont,
332  TRANS* transCont,
333  MsgStream &log) {
334  CONV element_cnv;
335  typename PERS::const_iterator it;
336  const typename PERS::HitVector& pvec = persCont->getVector();
337  transCont->clear();
338  transCont->reserve(pvec.size());
339  for (it = pvec.begin(); it != pvec.end(); ++it) {
340  transCont->push_back(element_cnv.createTransient(&(*it), log));
341  }
342  transCont->setName(persCont->name() );
343 }
344 
345 template<class TRANS, class PERS, class CONV>
346 void T_AthenaHitsVectorCnv<TRANS, PERS, CONV>::transToPers(const TRANS* transCont,
347  PERS* persCont,
348  MsgStream &log) {
349  size_t size = transCont->size();
350  typename PERS::HitVector& pvec = persCont->m_cont;
351  pvec.resize(size);
352  // convert vector entries one by one
353  CONV element_cnv;
354  typename TRANS::const_iterator it = transCont->begin();
355  typename PERS::iterator pit = pvec.begin();
356  while(size) {
357  element_cnv.transToPers( *it, &(*pit), log );
358  ++it; ++pit; --size;
359  }
360  persCont->m_name = transCont->Name();
361 }
362 
363 
364 //--------------------------------------------------------------------
365 /*
366  persToTrans() and transToPers() implementation for a converter between
367  transient IdentifiableContainer<T> and persistent std::vector<T>
368  This version assumes RDO collection returns an identifier as a unsigned int.
369 */
370 template<class TRANS, class PERS, class CONV>
371 void TPCnvIDCont<TRANS, PERS, CONV>::persToTrans(const PERS* persCont,
372  TRANS* transCont,
373  MsgStream &log)
374 {
375  typename PERS::const_iterator pers_elem;
376  for (pers_elem = persCont->begin(); pers_elem != persCont->end(); ++pers_elem) {
377  COLLECTION_t* coll = m_elementCnv.createTransient(&(*pers_elem), log);
378  // register the rdo collection in IDC
379  //typename COLLECTION_t::ID id_coll =
380  //IdentifierHash is_hash = hashFcn(id_coll);
381  unsigned int id_hash = transCont->idToHash((unsigned int)coll->identify());
382  StatusCode sc = transCont->addCollection(coll, id_hash);
383  if (sc.isFailure()) {
384  delete coll;
385  throw std::runtime_error("Failed to add collection to ID Container");
386  }
387  log << MSG::DEBUG << "TPCnvIDCont::persToTrans, collection, hash id=" << id_hash << ", added to Identifiable container." << endmsg;
388  }
389 }
390 
391 template<class TRANS, class PERS, class CONV>
392 void TPCnvIDCont<TRANS, PERS, CONV>::transToPers(const TRANS* transCont,
393  PERS* persCont,
394  MsgStream &log)
395 {
396  typename TRANS::const_iterator it_Coll = transCont->begin();
397  typename TRANS::const_iterator it_CollEnd = transCont->end();
398  int entries;
399  for (entries = 0; it_Coll != it_CollEnd; ++entries, ++it_Coll) {
400  persCont->resize(entries + 1);
401  m_elementCnv.transToPers(&(**it_Coll), &(*persCont)[entries], log);
402  }
403  log << MSG::DEBUG << "TPCnvIDCont::transToPers, container size was " << entries << endmsg;
404 }
405 
406 //--------------------------------------------------------------------
407 /*
408  persToTrans() and transToPers() implementation for a converter between
409  transient IdentifiableContainer<T> and persistent std::vector<T>
410  This version assumes RDO collection returns an identifier as an Identifier
411 */
412 template<class TRANS, class PERS, class CONV>
413 void TPCnvIDContFromIdentifier<TRANS, PERS, CONV>::persToTrans(const PERS* persCont,
414  TRANS* transCont,
415  MsgStream &log)
416 {
417  typename PERS::const_iterator pers_elem;
418  for (pers_elem = persCont->begin(); pers_elem != persCont->end(); ++pers_elem) {
419  COLLECTION_t* coll = m_elementCnv.createTransient(&(*pers_elem), log);
420  // register the rdo collection in IDC
421  //typename COLLECTION_t::ID id_coll =
422  //IdentifierHash is_hash = hashFcn(id_coll);
423  unsigned int id_hash = transCont->idToHash(coll->identify().get_identifier32().get_compact());
424  StatusCode sc = transCont->addCollection(coll, id_hash);
425  if (sc.isFailure()) {
426  delete coll;
427  throw std::runtime_error("Failed to add collection to ID Container");
428  }
429  log << MSG::DEBUG << "TPCnvIDContFromIdentifier::persToTrans, collection, hash id=" << id_hash << ", added to Identifiable container." << endmsg;
430  }
431 }
432 
433 template<class TRANS, class PERS, class CONV>
434 void TPCnvIDContFromIdentifier<TRANS, PERS, CONV>::transToPers(const TRANS* transCont,
435  PERS* persCont,
436  MsgStream &log)
437 {
438  typename TRANS::const_iterator it_Coll = transCont->begin();
439  typename TRANS::const_iterator it_CollEnd = transCont->end();
440  int entries;
441  for (entries = 0; it_Coll != it_CollEnd; ++entries, ++it_Coll) {
442  persCont->resize(entries + 1);
443  m_elementCnv.transToPers(&(**it_Coll), &(*persCont)[entries], log);
444  }
445  log << MSG::DEBUG << "TPCnvIDContFromIdentifier::transToPers, container size was " << entries << endmsg;
446 }