ATLAS Offline Software
CodeGenerator_v2.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 
6 // System include(s):
7 #include <ctime>
8 #include <locale>
9 #include <sys/stat.h>
10 
11 // STL include(s):
12 #include <fstream>
13 #include <sstream>
14 #include <algorithm>
15 
16 
17 // Gaudi/Athena include(s):
18 #include "GaudiKernel/System.h"
20 
21 // D3PD include(s):
23 
24 // Local include(s):
25 #include "CodeGenerator_v2.h"
27 #include "isPrimitive.h"
28 
30 static const char* const CODE_COMMENT =
31  "// Dear emacs, this is -*- c++ -*-\n"
32  "// -------------------------------------------------------------\n"
33  "// Code produced by D3PDMakerReader\n"
34  "//\n"
35  "// author: Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>\n"
36  "// -------------------------------------------------------------";
37 
39 #define FOR_ALL_EVENT_VARIABLES(EXP) { \
40  std::set< ObjectMetadata >::const_iterator meta_itr = \
41  metadata.begin(); \
42  std::set< ObjectMetadata >::const_iterator meta_end = \
43  metadata.end(); \
44  std::set< std::string > varnames; \
45  for( ; meta_itr != meta_end; ++meta_itr ) { \
46  const std::string varname = \
47  eventVariableName( meta_itr->prefix(), \
48  meta_itr->name(), \
49  varnames ); \
50  varnames.insert( varname ); \
51  EXP; \
52  } \
53  } while( 0 )
54 
55 namespace {
56 
58 
71  std::string vectorTemplateArgument( const std::string& type,
72  bool& ok ) {
73 
74  //
75  // Check that the type declaration begins with "std::vector<" or
76  // "vector<":
77  //
78  ok = true;
79  std::string result = type;
80  if( result.starts_with( "std::vector<" ) ) {
81  result.replace( 0, 12, "" );
82  } else if( result.starts_with( "vector<" ) ) {
83  result.replace( 0, 7, "" );
84  } else {
85  ok = false;
86  return "";
87  }
88 
89  //
90  // Now go through the characters one-by-one, and try to find the closing
91  // bracket of the template argument. Remember that the template argument
92  // can itself be a templated type (vector of a vector for instance), so
93  // the code has to remember how many brackets were opened and closed.
94  //
95  int brackets = 0;
96  for( size_t i = 0; i < result.size(); ++i ) {
97 
98  switch( result[ i ] ) {
99  case ',':
100  if( ! brackets ) {
101  return result.substr( 0, i );
102  }
103  break;
104  case '<':
105  ++brackets;
106  break;
107  case '>':
108  if( ! brackets ) {
109  // This is for the case when the vector's template argument is
110  // itself a template type:
111  if( result[ i - 1 ] == ' ' ) {
112  return result.substr( 0, i - 1 );
113  } else {
114  return result.substr( 0, i );
115  }
116  }
117  --brackets;
118  break;
119  default:
120  break;
121  }
122  }
123 
124  ok = false;
125  return "";
126  }
127 
129 
137  void addSTLHeader( std::ostream& out, const char* name,
138  const D3PD::ObjectMetadata& metadata ) {
139 
140  // Check if the STL name appears in the variable type names:
141  bool header_needed = false;
142  std::set< D3PD::ObjectMetadata::Variable >::const_iterator itr =
143  metadata.variables().begin();
144  std::set< D3PD::ObjectMetadata::Variable >::const_iterator end =
145  metadata.variables().end();
146  for( ; itr != end; ++itr ) {
147  if( itr->type().find( name ) != std::string::npos ) {
148  header_needed = true;
149  break;
150  }
151  }
152 
153  // If it does, let's include it:
154  if( header_needed ) {
155  out << "#include <" << name << ">" << std::endl;
156  // This statement is here to make sure that ROOT's type names such as
157  // "vector<float>" will be compilable as well:
158  out << "using std::" << name << ";" << std::endl;
159  }
160 
161  return;
162  }
163 
165 
173  std::string variableName( const std::string& varname ) {
174 
175  std::string result = varname;
176 
177  // Exchange the non C++-compilant characters:
178  std::string::size_type i = 0;
179  while( ( i = result.find( ":" ) ) != std::string::npos ) {
180  result[ i ] = '_';
181  }
182  while( ( i = result.find( " " ) ) != std::string::npos ) {
183  result[ i ] = '_';
184  }
185 
186  // If the first character is a number, preceed it with the
187  // letter 'x':
188  if( isdigit( result[ 0 ] ) ) {
189  result = "x" + result;
190  }
191 
192  return result;
193  }
194 
196 
212  std::string eventVariableName( const std::string& prefix,
213  const std::string& objectName,
214  const std::set< std::string >& varnames ) {
215 
216  // The resulting string:
217  std::string result;
218 
219  // If we have a prefix, use that as the variable name:
220  if( prefix.size() ) {
221  result = prefix;
222  // Remove a possible trailing underscore from the name:
223  if( result[ result.size() - 1 ] == '_' ) {
224  result.resize( prefix.size() - 1 );
225  }
226  // Return this variable name if it's not been used yet:
227  if( varnames.find( result ) == varnames.end() ) {
228  return result;
229  }
230  // Try to extend the variable name until it becomes unique:
231  for( int i = 0; ; ++i ) {
232  std::ostringstream name;
233  name << result << "_" << static_cast< char >( 'a' + i );
234  if( varnames.find( name.str() ) == varnames.end() ) {
235  return name.str();
236  }
237  }
238  }
239 
240  // If we don't have a prefix, let's use the object name:
241  result = objectName;
242  // Remove a posible "D3PDObject" from the name:
243  if( result.find( "D3PDObject" ) == result.size() - 10 ) {
244  result.resize( result.size() - 10 );
245  }
246  // Turn the string into all lower case:
247  std::transform(result.begin(), result.end(), result.begin(),[](unsigned char c){ return std::tolower(c); });
248  return result;
249  }
250 
251 } // private namespace
252 
253 namespace D3PD {
254 
255  namespace Version2 {
256 
265  StatusCode writeD3PDObjectBase( const std::string& dir ) {
266 
267  // Construct the file names as they will be needed in a few places:
268  const std::string headerName = dir + "/" + D3PDOBJECTBASE_HEADER_NAME;
269 
270  // Only create the header if it doesn't exist:
271  struct stat fileInfo;
272  if( stat( headerName.c_str(), &fileInfo ) ) {
273 
274  // Let everyone know what we're doing:
275  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO,
276  "Version2::writeD3PDObjectBase" )
277  << "Generating file: " << headerName;
278 
279  // Open the header file (overwriting a possibly existing file):
280  std::ofstream header( headerName.c_str() );
281 
282  // Write the header file:
283  header << D3PDOBJECTBASE_HEADER << std::endl;
284  header.close();
285  }
286 
287  return StatusCode::SUCCESS;
288  }
289 
298  StatusCode writeVarHandle( const std::string& dir ) {
299 
300  // Construct the file names as they will be needed in a few places:
301  const std::string headerName = dir + "/" + VARHANDLE_HEADER_NAME;
302  const std::string implName = dir + "/" + VARHANDLE_IMPL_NAME;
303  const std::string sourceName = dir + "/" + VARHANDLE_CXX_NAME;
304 
305  // Only create the header if it doesn't exist:
306  struct stat fileInfo;
307  if( stat( headerName.c_str(), &fileInfo ) ) {
308 
309  // Let everyone know what we're doing:
310  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO,
311  "Version2::writeVarHandle" )
312  << "Generating file: " << headerName;
313 
314  // Open the header file (overwriting a possibly existing file):
315  std::ofstream header( headerName.c_str() );
316 
317  // Write the header file:
318  header << VARHANDLE_HEADER << std::endl;
319  header.close();
320  }
321 
322  // Only create the implementation if it doesn't exist:
323  if( stat( implName.c_str(), &fileInfo ) ) {
324 
325  // Let everyone know what we're doing:
326  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeVarHandle" )
327  << "Generating file: " << implName;
328 
329  // Open the header file (overwriting a possibly existing file):
330  std::ofstream impl( implName.c_str() );
331 
332  // Write the header file:
333  impl << VARHANDLE_IMPL << std::endl;
334  impl.close();
335  }
336 
337  // Only create the source if it doesn't exist:
338  if( stat( sourceName.c_str(), &fileInfo ) ) {
339 
340  // Let everyone know what we're doing:
341  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeVarHandle" )
342  << "Generating file: " << sourceName;
343 
344  // Open the header file (overwriting a possibly existing file):
345  std::ofstream source( sourceName.c_str() );
346 
347  // Write the header file:
348  source << VARHANDLE_CXX << std::endl;
349  source.close();
350  }
351 
352  return StatusCode::SUCCESS;
353  }
354 
363  StatusCode writeVarProxy( const std::string& dir ) {
364 
365  // Construct the file names as they will be needed in a few places:
366  const std::string headerName = dir + "/" + VARPROXY_HEADER_NAME;
367  const std::string implName = dir + "/" + VARPROXY_IMPL_NAME;
368 
369  // Only create the header if it doesn't exist:
370  struct stat fileInfo;
371  if( stat( headerName.c_str(), &fileInfo ) ) {
372 
373  // Let everyone know what we're doing:
374  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeVarProxy" )
375  << "Generating file: " << headerName;
376 
377  // Open the header file (overwriting a possibly existing file):
378  std::ofstream header( headerName.c_str() );
379 
380  // Write the header file:
381  header << VARPROXY_HEADER << std::endl;
382  header.close();
383  }
384 
385  // Only create the implementation if it doesn't exist:
386  if( stat( implName.c_str(), &fileInfo ) ) {
387 
388  // Let everyone know what we're doing:
389  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeVarProxy" )
390  << "Generating file: " << implName;
391 
392  // Open the header file (overwriting a possibly existing file):
393  std::ofstream impl( implName.c_str() );
394 
395  // Write the header file:
396  impl << VARPROXY_IMPL << std::endl;
397  impl.close();
398  }
399 
400  return StatusCode::SUCCESS;
401  }
402 
411  StatusCode writeUserD3PDObject( const std::string& dir ) {
412 
413  // Construct the file names as they will be needed in a few places:
414  const std::string headerName = dir + "/" + USERD3PDOBJECT_HEADER_NAME;
415  const std::string implName = dir + "/" + USERD3PDOBJECT_IMPL_NAME;
416  const std::string sourceName = dir + "/" + USERD3PDOBJECT_CXX_NAME;
417 
418  // Only create the header if it doesn't exist:
419  struct stat fileInfo;
420  if( stat( headerName.c_str(), &fileInfo ) ) {
421 
422  // Let everyone know what we're doing:
423  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO,
424  "Version2::writeUserD3PDObject" )
425  << "Generating file: " << headerName;
426 
427  // Open the header file (overwriting a possibly existing file):
428  std::ofstream header( headerName.c_str() );
429 
430  // Write the header file:
431  header << USERD3PDOBJECT_HEADER << std::endl;
432  header.close();
433  }
434 
435  // Only create the implementation if it doesn't exist:
436  if( stat( implName.c_str(), &fileInfo ) ) {
437 
438  // Let everyone know what we're doing:
439  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO,
440  "Version2::writeUserD3PDObject" )
441  << "Generating file: " << implName;
442 
443  // Open the header file (overwriting a possibly existing file):
444  std::ofstream impl( implName.c_str() );
445 
446  // Write the header file:
447  impl << USERD3PDOBJECT_IMPL << std::endl;
448  impl.close();
449  }
450 
451  // Only create the source if it doesn't exist:
452  if( stat( sourceName.c_str(), &fileInfo ) ) {
453 
454  // Let everyone know what we're doing:
455  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO,
456  "Version2::writeUserD3PDObject" )
457  << "Generating file: " << sourceName;
458 
459  // Open the header file (overwriting a possibly existing file):
460  std::ofstream source( sourceName.c_str() );
461 
462  // Write the header file:
463  source << USERD3PDOBJECT_CXX << std::endl;
464  source.close();
465  }
466 
467  return StatusCode::SUCCESS;
468  }
469 
478  StatusCode writeD3PDReadStats( const std::string& dir ) {
479 
480  // Construct the file names as they will be needed in a few places:
481  const std::string headerName = dir + "/" + D3PDREADSTATS_HEADER_NAME;
482  const std::string cxxName = dir + "/" + D3PDREADSTATS_CXX_NAME;
483 
484  // Only create the header if it doesn't exist:
485  struct stat fileInfo;
486  if( stat( headerName.c_str(), &fileInfo ) ) {
487 
488  // Let everyone know what we're doing:
489  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO,
490  "Version2::writeD3PDReadStats" )
491  << "Generating file: " << headerName;
492 
493  // Open the header file (overwriting a possibly existing file):
494  std::ofstream header( headerName.c_str() );
495 
496  // Write the header file:
497  header << D3PDREADSTATS_HEADER << std::endl;
498  header.close();
499  }
500 
501  // Only create the implementation if it doesn't exist:
502  if( stat( cxxName.c_str(), &fileInfo ) ) {
503 
504  // Let everyone know what we're doing:
505  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO,
506  "Version2::writeD3PDReadStats" )
507  << "Generating file: " << cxxName;
508 
509  // Open the header file (overwriting a possibly existing file):
510  std::ofstream impl( cxxName.c_str() );
511 
512  // Write the header file:
513  impl << D3PDREADSTATS_CXX << std::endl;
514  impl.close();
515  }
516 
517  return StatusCode::SUCCESS;
518  }
519 
528  StatusCode writeD3PDPerfStats( const std::string& dir ) {
529 
530  // Construct the file names as they will be needed in a few places:
531  const std::string headerName = dir + "/" + D3PDPERFSTATS_HEADER_NAME;
532  const std::string cxxName = dir + "/" + D3PDPERFSTATS_CXX_NAME;
533 
534  // Only create the header if it doesn't exist:
535  struct stat fileInfo;
536  if( stat( headerName.c_str(), &fileInfo ) ) {
537 
538  // Let everyone know what we're doing:
539  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO,
540  "Version2::writeD3PDPerfStats" )
541  << "Generating file: " << headerName;
542 
543  // Open the header file (overwriting a possibly existing file):
544  std::ofstream header( headerName.c_str() );
545 
546  // Write the header file:
547  header << D3PDPERFSTATS_HEADER << std::endl;
548  header.close();
549  }
550 
551  // Only create the implementation if it doesn't exist:
552  if( stat( cxxName.c_str(), &fileInfo ) ) {
553 
554  // Let everyone know what we're doing:
555  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO,
556  "Version2::writeD3PDPerfStats" )
557  << "Generating file: " << cxxName;
558 
559  // Open the header file (overwriting a possibly existing file):
560  std::ofstream impl( cxxName.c_str() );
561 
562  // Write the header file:
563  impl << D3PDPERFSTATS_CXX << std::endl;
564  impl.close();
565  }
566 
567  return StatusCode::SUCCESS;
568  }
569 
577  StatusCode writeUtils( const std::string& dir ) {
578 
579  // Construct the file names as they will be needed in a few places:
580  const std::string headerName = dir + "/" + UTILS_HEADER_NAME;
581  const std::string cxxName = dir + "/" + UTILS_CXX_NAME;
582 
583  // Only create the header if it doesn't exist:
584  struct stat fileInfo;
585  if( stat( headerName.c_str(), &fileInfo ) ) {
586 
587  // Let everyone know what we're doing:
588  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeUtils" )
589  << "Generating file: " << headerName;
590 
591  // Open the header file (overwriting a possibly existing file):
592  std::ofstream header( headerName.c_str() );
593 
594  // Write the header file:
595  header << UTILS_HEADER << std::endl;
596  header.close();
597  }
598 
599  // Only create the implementation if it doesn't exist:
600  if( stat( cxxName.c_str(), &fileInfo ) ) {
601 
602  // Let everyone know what we're doing:
603  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeUtils" )
604  << "Generating file: " << cxxName;
605 
606  // Open the header file (overwriting a possibly existing file):
607  std::ofstream impl( cxxName.c_str() );
608 
609  // Write the header file:
610  impl << UTILS_CXX << std::endl;
611  impl.close();
612  }
613 
614  return StatusCode::SUCCESS;
615  }
616 
632  StatusCode writeHeader( const std::string& classname,
633  const std::string& dir,
634  const ObjectMetadata& metadata ) {
635 
636  // Construct the file name:
637  const std::string fileName = dir + "/" + classname + ".h";
638 
639  // If the file already exists, let's not overwrite it:
640  struct stat fileInfo;
641  if( ! stat( fileName.c_str(), &fileInfo ) ) return StatusCode::SUCCESS;
642 
643  // Let everyone know what we're doing:
644  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeHeader" )
645  << "Generating file: " << fileName;
646 
647  // Open the header file (overwriting a possibly existing file):
648  std::ofstream header( fileName.c_str() );
649 
650  // Write a header for the file:
651  header << CODE_COMMENT << std::endl;
652  header << "#ifndef D3PDREADER_" << classname << "_H" << std::endl;
653  header << "#define D3PDREADER_" << classname << "_H" << std::endl
654  << std::endl;
655 
656  // The STL map is always needed:
657  header << "// STL include(s):" << std::endl;
658  header << "#include <map>" << std::endl;
659 
660  // Include some other STL headers if they're needed:
661  addSTLHeader( header, "vector", metadata );
662  addSTLHeader( header, "string", metadata );
663  header << std::endl;
664 
665  // ROOT include(s):
666  header << "// ROOT include(s):" << std::endl;
667  header << "#include <TObject.h>" << std::endl;
668  header << "#include <TString.h>" << std::endl << std::endl;
669 
670  // Local include(s):
671  header << "#include \"" << D3PDOBJECTBASE_HEADER_NAME << "\""
672  << std::endl;
673  header << "#include \"" << D3PDREADSTATS_HEADER_NAME << "\""
674  << std::endl;
675  header << "#include \"" << VARHANDLE_HEADER_NAME << "\"" << std::endl;
676  if( metadata.container() ) {
677  header << "#include \"" << VARPROXY_HEADER_NAME << "\""
678  << std::endl;
679  }
680  header << "#include \"" << USERD3PDOBJECT_HEADER_NAME << "\""
681  << std::endl;
682  header << std::endl;
683 
684  // Forward declaration(s):
685  header << "class TTree;" << std::endl << std::endl;
686 
687  // Declare the namespace:
688  header << "namespace D3PDReader {" << std::endl << std::endl;
689 
690  //
691  // Declare the proxy class:
692  //
693  if( metadata.container() ) {
694 
695  // Forward declare the reader class:
696  header << " // Forward declaration(s):" << std::endl;
697  header << " class " << classname << ";" << std::endl << std::endl;
698 
699  // Declare the proxy class:
700  header << " /**" << std::endl;
701  header << " * Code generated by CodeGenerator_v2 on:"
702  << std::endl;
703  header << " * host = " << System::hostName() << std::endl;
704  header << " * OS = " << System::osName() << " / "
705  << System::osVersion() << std::endl;
706  header << " * user = " << System::accountName() << std::endl;
707  const time_t rawtime = time( NULL );
708  char buf[26];
709  header << " * time = " << ctime_r( &rawtime, buf );
710  header << " */" << std::endl;
711  header << " class " << classname << "Element : "
712  << "public UserD3PDObjectElement {" << std::endl
713  << std::endl;
714  header << " friend class " << classname << ";" << std::endl
715  << std::endl;
716  header << " protected:" << std::endl;
717 
718  // Create the constructor:
719  header << " /// Constructor only visible to " << classname
720  << std::endl;
721  header << " " << classname << "Element( size_t index, const "
722  << classname << "& parent );" << std::endl << std::endl;
723 
724  // Create the copy constructor:
725  header << " public:" << std::endl;
726  header << " /// Copy constructor" << std::endl;
727  header << " " << classname << "Element( const " << classname
728  << "Element& parent );" << std::endl << std::endl;
729 
730  // Create the generic accessor functions:
731  header << " /// Parent object of this proxy object"
732  << std::endl;
733  header << " const " << classname << "* GetParent() const;"
734  << std::endl;
735  header << " /// Index of the object inside its container"
736  << std::endl;
737  header << " size_t GetIndex() const;" << std::endl
738  << std::endl;
739 
740  // Create the member variable(s):
741  std::map< std::string, int > variableCounter;
742  std::set< ObjectMetadata::Variable >::const_iterator itr =
743  metadata.variables().begin();
744  std::set< ObjectMetadata::Variable >::const_iterator end =
745  metadata.variables().end();
746  for( ; itr != end; ++itr ) {
747  // Ignore the container size variable:
748  if( ( itr->name() == "n" ) || ( itr->name() == "N" ) ) continue;
749 
750  bool ok = true;
751  const std::string type =
752  vectorTemplateArgument( itr->type(), ok );
753  if( ! ok ) {
754  REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR,
755  "Version2::writeHeader" )
756  << "Unexpected variable type encountered for "
757  << "container dumper: " << itr->type();
758  REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR,
759  "Version2::writeHeader" )
760  << "Variable name: " << itr->name();
761  return StatusCode::FAILURE;
762  }
763  if( itr->doc() != "" ) {
764  header << " /// " << itr->doc() << std::endl;
765  }
766  if( variableCounter.find( itr->name() ) ==
767  variableCounter.end() ) {
768  header << " VarProxy< " << type << " > "
769  << variableName( itr->name() ) << ";" << std::endl;
770  variableCounter[ itr->name() ] = 1;
771  } else {
772  header << " VarProxy< " << type << " > "
773  << variableName( itr->name() )
774  << variableCounter[ itr->name() ] << ";" << std::endl;
775  variableCounter[ itr->name() ]++;
776  }
777  }
778  header << std::endl;
779 
780  // Create the private variable(s):
781  header << " private:" << std::endl;
782  header << " /// Reference to the parent of this object"
783  << std::endl;
784  header << " const " << classname << "* fParent;" << std::endl;
785  header << " /// The index of this object inside the parent "
786  << "container" << std::endl;
787  header << " size_t fIndex;" << std::endl << std::endl;
788 
789  // Close the class definition:
790  header << " ClassDef( " << classname << "Element, 0 )"
791  << std::endl
792  << std::endl;
793  header << " }; // class " << classname << "Element" << std::endl
794  << std::endl;
795  }
796 
797  //
798  // Declare the reader class itself:
799  //
800  header << " /**" << std::endl;
801  header << " * Code generated by CodeGenerator_v2 on:" << std::endl;
802  header << " * host = " << System::hostName() << std::endl;
803  header << " * OS = " << System::osName() << " / "
804  << System::osVersion() << std::endl;
805  header << " * user = " << System::accountName() << std::endl;
806  const time_t rawtime = time( NULL );
807  char buf[26];
808  header << " * time = " << ctime_r( &rawtime, buf );
809  header << " */" << std::endl;
810  header << " class " << classname << " : "
811  << "public UserD3PDObject {" << std::endl << std::endl;
812  header << " public:" << std::endl;
813 
814  //
815  // Declare the constructor(s)/destructor:
816  //
817  header << " /// Constructor used when reading from a TTree"
818  << std::endl;
819  header << " " << classname
820  << "( const ::Long64_t& master, const char* prefix = \""
821  << metadata.prefix() << "\" );" << std::endl;
822  header << " /// Constructor when the object is only used for "
823  << "writing data out" << std::endl;
824  header << " " << classname << "( const char* prefix = \""
825  << metadata.prefix() << "\" );" << std::endl;
826  if( metadata.container() ) {
827  header << " /// Destructor" << std::endl;
828  header << " ~" << classname << "();" << std::endl;
829  }
830  header << std::endl;
831 
832  //
833  // Declare some functions:
834  //
835  header << " /// Get the currently configured prefix value"
836  << std::endl;
837  header << " virtual const char* GetPrefix() const;" << std::endl;
838  header << " /// Set the prefix for the variables" << std::endl;
839  header << " virtual void SetPrefix( const char* prefix );"
840  << std::endl << std::endl;
841 
842  header << " /// Connect the object to an input TTree"
843  << std::endl;
844  header << " virtual void ReadFrom( ::TTree* tree );" << std::endl;
845  header << " /// Connect the object to an output TTree"
846  << std::endl;
847  header << " virtual void WriteTo( ::TTree* tree );" << std::endl
848  << std::endl;
849 
850  header << " /// Turn (selected) branches either on or off"
851  << std::endl;
852  header << " virtual void SetActive( ::Bool_t active = kTRUE,"
853  << std::endl;
854  header << " const ::TString& pattern = "
855  << "\".*\" );" << std::endl;
856  header << " /// Read in all the variables that we need to write "
857  << "out as well" << std::endl;
858  header << " virtual void ReadAllActive();" << std::endl
859  << std::endl;
860 
861  header << " /// Get the D3PD reading statistics" << std::endl;
862  header << " virtual D3PDReadStats GetStatistics() const;"
863  << std::endl << std::endl;
864 
865  header << " /// Set the contents of the object according to "
866  << "another object" << std::endl;
867  header << " " << classname << "& Set( const " << classname
868  << "& parent );" << std::endl << std::endl;
869 
870  if( metadata.container() ) {
871  header << " /// Clear the container. Useful when writing new "
872  << "branches." << std::endl;
873  header << " void Clear( Option_t* option = \"\" );"
874  << std::endl;
875  header << " /// Add one element to an output collection"
876  << std::endl;
877  header << " " << classname << "& Add( const " << classname
878  << "Element& el );" << std::endl << std::endl;
879  header << " /// Access a proxy class describing one element of"
880  << " the container" << std::endl;
881  header << " " << classname << "Element& operator[]( size_t "
882  << "index );" << std::endl;
883  header << " /// Access a proxy class describing one element of"
884  << " the container (constant version)" << std::endl;
885  header << " const " << classname << "Element& operator[]( "
886  << "size_t index ) const;" << std::endl;
887  header << " /// Add one element to an output collection"
888  << std::endl;
889  header << " " << classname << "& operator+=( const "
890  << classname << "Element& el );" << std::endl << std::endl;
891  }
892 
893  //
894  // Declare each variable responsible for reading a branch:
895  //
896  std::map< std::string, int > variableCounter;
897  std::set< ObjectMetadata::Variable >::const_iterator itr =
898  metadata.variables().begin();
899  std::set< ObjectMetadata::Variable >::const_iterator end =
900  metadata.variables().end();
901  for( ; itr != end; ++itr ) {
902  if( itr->doc() != "" ) {
903  header << " /// " << itr->doc() << std::endl;
904  }
905  if( variableCounter.find( itr->name() ) == variableCounter.end() ) {
906  header << " VarHandle< " << itr->type()
907  << ( itr->primitive() ? "" : "*" ) << " > "
908  << variableName( itr->name() ) << ";" << std::endl;
909  variableCounter[ itr->name() ] = 1;
910  } else {
911  header << " VarHandle< " << itr->type()
912  << ( itr->primitive() ? "" : "*" ) << " > "
913  << variableName( itr->name() )
914  << variableCounter[ itr->name() ] << ";" << std::endl;
915  variableCounter[ itr->name() ]++;
916  }
917  }
918 
919  // Declare the private functions/members:
920  header << std::endl << " private:" << std::endl;
921  header << " /// Function used internally to access the variables"
922  << std::endl;
923  header << " VarHandleBase* GetVarHandle( const char* name );"
924  << std::endl;
925  header << " /// Function setting up all the VarHandle members"
926  << std::endl;
927  header << " void SetVarHandles( const ::Long64_t* master );"
928  << std::endl << std::endl;
929 
930  // Declare the additional member variable(s):
931  if( metadata.container() ) {
932  header << " mutable std::vector< " << classname << "Element* >"
933  << " fProxies; ///< Internal list of proxy objects"
934  << std::endl;
935  }
936  header << " std::map< ::TString, VarHandleBase* > fHandles; "
937  << "///< Book-keeper of the VarHandle members" << std::endl;
938  header << " const ::Bool_t fFromInput; "
939  << "///< Flag specifying if object is used for D3PD reading"
940  << std::endl;
941  header << " ::TString fPrefix; ///< Prefix to the branch names"
942  << std::endl << std::endl;
943 
944  // Close the class definition:
945  header << " ClassDef( " << classname << ", 0 )" << std::endl
946  << std::endl;
947  header << " }; // class " << classname << std::endl << std::endl;
948  header << "} // namespace D3PDReader" << std::endl << std::endl;
949  header << "#endif // D3PDREADER_" << classname << "_H" << std::endl;
950 
951  header.close();
952 
953  return StatusCode::SUCCESS;
954  }
955 
967  StatusCode writeSource( const std::string& classname,
968  const std::string& dir,
969  const ObjectMetadata& metadata ) {
970 
971  // Construct the file name:
972  const std::string fileName = dir + "/" + classname + ".cxx";
973 
974  // If the file already exists, let's not overwrite it:
975  struct stat fileInfo;
976  if( ! stat( fileName.c_str(), &fileInfo ) ) return StatusCode::SUCCESS;
977 
978  // Let everyone know what we're doing:
979  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeSource" )
980  << "Generating file: " << fileName;
981 
982  // Open the header file (overwriting a possibly existing file):
983  std::ofstream source( fileName.c_str() );
984 
985  // Add the common header to the file:
986  source << CODE_COMMENT << std::endl << std::endl;
987 
988  if( metadata.container() ) {
989  source << "#include <limits>" << std::endl;
990  source << "#include <stdexcept>" << std::endl << std::endl;
991  }
992 
993  // Extra ROOT include(s):
994  source << "#include <TPRegexp.h>" << std::endl;
995  source << "#include <TList.h>" << std::endl;
996  source << "#include <TDataMember.h>" << std::endl << std::endl;
997 
998  // Include the class's header:
999  source << "#include \"" << classname << ".h\"" << std::endl
1000  << std::endl;
1001 
1002  if( metadata.container() ) {
1003  source << "ClassImp( D3PDReader::" << classname << "Element )"
1004  << std::endl;
1005  }
1006  source << "ClassImp( D3PDReader::" << classname << " )" << std::endl
1007  << std::endl;
1008 
1009  source << "namespace D3PDReader {" << std::endl << std::endl;
1010 
1011  if( metadata.container() ) {
1012  //
1013  // Produce the constructor of the proxy class:
1014  //
1015  const std::string spacer( ( 2 * classname.size() ) + 21, ' ' );
1016  source << " /**" << std::endl;
1017  source << " * This constructor can be used to create new proxy "
1018  << "objects from scratch." << std::endl;
1019  source << " * Since the constructor of such an object is quite "
1020  << "complicated and" << std::endl;
1021  source << " * error prone, it is only visible to the parent "
1022  << "class " << classname << "." << std::endl;
1023  source << " */" << std::endl;
1024  source << " " << classname << "Element::" << classname
1025  << "Element( size_t index, const " << classname
1026  << "& parent )" << std::endl;
1027  source << " : UserD3PDObjectElement( index, parent )";
1028  std::map< std::string, int > variableCounter;
1029  std::set< ObjectMetadata::Variable >::const_iterator itr =
1030  metadata.variables().begin();
1031  std::set< ObjectMetadata::Variable >::const_iterator end =
1032  metadata.variables().end();
1033  for( ; itr != end; ++itr ) {
1034  // Ignore the container size variable:
1035  if( ( itr->name() == "n" ) || ( itr->name() == "N" ) ) continue;
1036 
1037  source << "," << std::endl;
1038  if( variableCounter.find( itr->name() ) ==
1039  variableCounter.end() ) {
1040  source << " " << variableName( itr->name() )
1041  << "( parent." << variableName( itr->name() )
1042  << ", index )";
1043  variableCounter[ itr->name() ] = 1;
1044  } else {
1045  source << " " << variableName( itr->name() )
1046  << variableCounter[ itr->name() ]
1047  << "( parent." << variableName( itr->name() )
1048  << variableCounter[ itr->name() ] << ", index )";
1049  variableCounter[ itr->name() ]++;
1050  }
1051  }
1052  source << "," << std::endl;
1053  source << " fParent( &parent ), fIndex( index ) {"
1054  << std::endl << std::endl;
1055  source << " }" << std::endl << std::endl;
1056 
1057  //
1058  // Produce the copy-constructor of the proxy class:
1059  //
1060  source << " /**" << std::endl;
1061  source << " * This constructor is useful for creating copies of "
1062  << "proxy objects." << std::endl;
1063  source << " * Such objects are fairly cheap to copy, so the user"
1064  << " is allowed to have" << std::endl;
1065  source << " * his/her containers of them inside an analysis "
1066  << "code. (To select and" << std::endl;
1067  source << " * sort objects according to some criteria for "
1068  << "instance.)" << std::endl;
1069  source << " *" << std::endl;
1070  source << " * @param parent The proxy object that should be "
1071  << "copied" << std::endl;
1072  source << " */" << std::endl;
1073  source << " " << classname << "Element::" << classname
1074  << "Element( const " << classname << "Element& parent )"
1075  << std::endl;
1076  source << " : UserD3PDObjectElement( parent )";
1077  variableCounter.clear();
1078  itr = metadata.variables().begin();
1079  end = metadata.variables().end();
1080  for( ; itr != end; ++itr ) {
1081  // Ignore the container size variable:
1082  if( ( itr->name() == "n" ) || ( itr->name() == "N" ) ) continue;
1083 
1084  source << "," << std::endl;
1085  if( variableCounter.find( itr->name() ) ==
1086  variableCounter.end() ) {
1087  source << " " << variableName( itr->name() )
1088  << "( parent." << variableName( itr->name() )
1089  << " )";
1090  variableCounter[ itr->name() ] = 1;
1091  } else {
1092  source << " " << variableName( itr->name() )
1093  << variableCounter[ itr->name() ]
1094  << "( parent." << variableName( itr->name() )
1095  << variableCounter[ itr->name() ] << " )";
1096  variableCounter[ itr->name() ]++;
1097  }
1098  }
1099  source << "," << std::endl;
1100  source << " fParent( parent.fParent ), "
1101  << "fIndex( parent.fIndex ) {" << std::endl << std::endl;
1102  source << " }" << std::endl << std::endl;
1103 
1104  //
1105  // Produce the GetParent() function of the proxy class:
1106  //
1107  source << " /**" << std::endl;
1108  source << " * This function can be used to access the parent "
1109  << "object of this" << std::endl;
1110  source << " * proxy object. It can come in handy when optimizing"
1111  << " an analysis code." << std::endl;
1112  source << " *" << std::endl;
1113  source << " * @returns A reference to this object's parent"
1114  << std::endl;
1115  source << " */" << std::endl;
1116  source << " const " << classname << "* " << classname
1117  << "Element::GetParent() const {" << std::endl << std::endl;
1118  source << " return fParent;" << std::endl;
1119  source << " }" << std::endl << std::endl;
1120 
1121  //
1122  // Produce the GetIndex() function of the proxy class:
1123  //
1124  source << " /**" << std::endl;
1125  source << " * This function can be used to access the index of "
1126  << "this proxy object" << std::endl;
1127  source << " * inside the parent container. It can come in handy "
1128  << "when optimizing an" << std::endl;
1129  source << " * analysis code." << std::endl;
1130  source << " *" << std::endl;
1131  source << " * @returns The index of the proxy in the object's "
1132  << "parent" << std::endl;
1133  source << " */" << std::endl;
1134  source << " size_t " << classname << "Element::GetIndex() const {"
1135  << std::endl << std::endl;
1136  source << " return fIndex;" << std::endl;
1137  source << " }" << std::endl << std::endl;
1138  }
1139 
1140  //
1141  // Produce the (input) constructor:
1142  //
1143  source << " /**" << std::endl;
1144  source << " * This constructor should be used when the object will "
1145  << "be used to read" << std::endl;
1146  source << " * variables from an existing ntuple. The object will "
1147  << "also be able to" << std::endl;
1148  source << " * output variables, but it will also need to read them "
1149  << "from somewhere." << std::endl;
1150  source << " *" << std::endl;
1151  source << " * @param master Reference to the variable holding the "
1152  << "current " << "event number" << std::endl;
1153  source << " * @param prefix Prefix of the variables in the D3PD"
1154  << std::endl;
1155  source << " */" << std::endl;
1156  source << " " << classname << "::" << classname
1157  << "( const ::Long64_t& master, const char* prefix )"
1158  << std::endl;
1159  source << " : UserD3PDObject( master, prefix ),"
1160  << std::endl;
1161  source << " fHandles()," << std::endl;
1162  source << " fFromInput( kTRUE )," << std::endl;
1163  source << " fPrefix( prefix ) {" << std::endl << std::endl;
1164  source << " SetVarHandles( &master );" << std::endl;
1165  source << " }" << std::endl << std::endl;
1166 
1167  //
1168  // Produce the (output) constructor:
1169  //
1170  source << " /**" << std::endl;
1171  source << " * This constructor can be used when the object will "
1172  << "only have to output" << std::endl;
1173  source << " * (and temporarily store) new information into an "
1174  << "output ntuple. For" << std::endl;
1175  source << " * instance when one wants to create a selected/modified"
1176  << " list of information." << std::endl;
1177  source << " *" << std::endl;
1178  source << " * @param prefix Prefix of the variables in the D3PD"
1179  << std::endl;
1180  source << " */" << std::endl;
1181  source << " " << classname << "::" << classname
1182  << "( const char* prefix )" << std::endl;
1183  source << " : UserD3PDObject( prefix ),"
1184  << std::endl;
1185  source << " fHandles()," << std::endl;
1186  source << " fFromInput( kFALSE )," << std::endl;
1187  source << " fPrefix( prefix ) {" << std::endl << std::endl;
1188  source << " SetVarHandles( 0 );" << std::endl;
1189  source << " }" << std::endl << std::endl;
1190 
1191  //
1192  // Produce the destructor:
1193  //
1194  if( metadata.container() ) {
1195  source << " /**" << std::endl;
1196  source << " * The destructor needs to delete all the allocated "
1197  << "objects." << std::endl;
1198  source << " */" << std::endl;
1199  source << " " << classname << "::~" << classname << "() {"
1200  << std::endl
1201  << std::endl;
1202  source << " for( size_t i = 0; i < fProxies.size(); ++i ) {"
1203  << std::endl;
1204  source << " delete fProxies[ i ];" << std::endl;
1205  source << " }" << std::endl;
1206  source << " }" << std::endl << std::endl;
1207  }
1208 
1209  //
1210  // Produce the prefix handling function(s):
1211  //
1212  source << " /**" << std::endl;
1213  source << " * @returns The branch name prefix used by the object"
1214  << std::endl;
1215  source << " */" << std::endl;
1216  source << " const char* " << classname << "::GetPrefix() const {"
1217  << std::endl << std::endl;
1218  source << " return fPrefix;" << std::endl;
1219  source << " }" << std::endl << std::endl;
1220 
1221  source << " /**" << std::endl;
1222  source << " * @param prefix The prefix that should be used for the "
1223  << "variables" << std::endl;
1224  source << " */" << std::endl;
1225  source << " void " << classname << "::SetPrefix( const char* prefix "
1226  << ") {" << std::endl << std::endl;
1227  source << " // Call the base class's function:" << std::endl;
1228  source << " UserD3PDObject::SetPrefix( prefix );" << std::endl
1229  << std::endl;
1230  source << " // Remember the prefix:" << std::endl;
1231  source << " fPrefix = prefix;" << std::endl << std::endl;
1232  source << " // Set all the variable names:" << std::endl;
1233  source << " std::map< TString, VarHandleBase* >::const_iterator "
1234  << "itr = fHandles.begin();" << std::endl;
1235  source << " std::map< TString, VarHandleBase* >::const_iterator "
1236  << "end = fHandles.end();" << std::endl;
1237  source << " for( ; itr != end; ++itr ) {" << std::endl;
1238  source << " itr->second->SetName( ::TString( prefix ) + "
1239  << "itr->first );" << std::endl;
1240  source << " }" << std::endl << std::endl;
1241  source << " return;" << std::endl;
1242  source << " }" << std::endl << std::endl;
1243 
1244  //
1245  // Produce the ReadFrom(...) function:
1246  //
1247  source << " /**" << std::endl;
1248  source << " * This function should be called every time a new TFile"
1249  << " is opened" << std::endl;
1250  source << " * by your analysis code." << std::endl;
1251  source << " *" << std::endl;
1252  source << " * @param tree Pointer to the TTree with the variables"
1253  << std::endl;
1254  source << " */" << std::endl;
1255  source << " void " << classname << "::ReadFrom( TTree* tree ) {"
1256  << std::endl << std::endl;
1257  source << " // Check if the object will be able to read from the "
1258  << "TTree:" << std::endl;
1259  source << " if( ! fFromInput ) {" << std::endl;
1260  source << " Error( \"ReadFrom\", \"The object was not created "
1261  << "with the correct\" );" << std::endl;
1262  source << " Error( \"ReadFrom\", \"constructor to read data "
1263  << "from a D3PD!\" );" << std::endl;
1264  source << " return;" << std::endl;
1265  source << " }" << std::endl << std::endl;
1266  source << " // Call the base class's function:" << std::endl;
1267  source << " UserD3PDObject::ReadFrom( tree );" << std::endl
1268  << std::endl;
1269  source << " // Call ReadFrom(...) on all the variables:"
1270  << std::endl;
1271  source << " std::map< TString, VarHandleBase* >::const_iterator "
1272  << "itr = fHandles.begin();" << std::endl;
1273  source << " std::map< TString, VarHandleBase* >::const_iterator "
1274  << "end = fHandles.end();" << std::endl;
1275  source << " for( ; itr != end; ++itr ) {" << std::endl;
1276  source << " itr->second->ReadFrom( tree );" << std::endl;
1277  source << " }" << std::endl << std::endl;
1278  source << " return;" << std::endl;
1279  source << " }" << std::endl << std::endl;
1280 
1281  //
1282  // Produce the WriteTo(...) function:
1283  //
1284  source << " /**" << std::endl;
1285  source << " * This function can be called to connect the active "
1286  << "variables of the object" << std::endl;
1287  source << " * to an output TTree. It can be called multiple times, "
1288  << "then the variables" << std::endl;
1289  source << " * will be written to multiple TTrees." << std::endl;
1290  source << " *" << std::endl;
1291  source << " * @param tree Pointer to the TTree where the variables "
1292  << "should be written" << std::endl;
1293  source << " */" << std::endl;
1294  source << " void " << classname << "::WriteTo( TTree* tree ) {"
1295  << std::endl << std::endl;
1296  source << " // Call the base class's function:" << std::endl;
1297  source << " UserD3PDObject::WriteTo( tree );" << std::endl
1298  << std::endl;
1299  source << " // Call WriteTo(...) on all the variables:"
1300  << std::endl;
1301  source << " std::map< TString, VarHandleBase* >::const_iterator "
1302  << "itr = fHandles.begin();" << std::endl;
1303  source << " std::map< TString, VarHandleBase* >::const_iterator "
1304  << "end = fHandles.end();" << std::endl;
1305  source << " for( ; itr != end; ++itr ) {" << std::endl;
1306  source << " itr->second->WriteTo( tree );" << std::endl;
1307  source << " }" << std::endl << std::endl;
1308  source << " return;" << std::endl;
1309  source << " }" << std::endl << std::endl;
1310 
1311  //
1312  // Produce the SetActive(...) function:
1313  //
1314  source << " /**" << std::endl;
1315  source << " * This is a convenience function for turning the "
1316  << "branches active or" << std::endl;
1317  source << " * inactive conveniently. If the parameter is set to "
1318  << "<code>kTRUE</code>" << std::endl;
1319  source << " * then the branches available from the input which "
1320  << "match the given" << std::endl;
1321  source << " * pattern are turned active."
1322  << std::endl;
1323  source << " * When it's set to <code>kFALSE</code> then all the "
1324  << "variables matching" << std::endl;
1325  source << " * the pattern are turned inactive." << std::endl;
1326  source << " *" << std::endl;
1327  source << " * @param active Flag behaving as explained above"
1328  << std::endl;
1329  source << " * @param pattern Regular expression specifying which "
1330  << "branches to modify" << std::endl;
1331  source << " */" << std::endl;
1332  source << " void " << classname << "::SetActive( ::Bool_t active, "
1333  << "const ::TString& pattern ) {" << std::endl
1334  << std::endl;
1335  source << " // Call the base class's function:" << std::endl;
1336  source << " UserD3PDObject::SetActive( active, pattern );"
1337  << std::endl << std::endl;
1338  source << " ::TPRegexp re( pattern );" << std::endl << std::endl;
1339  source << " std::map< TString, VarHandleBase* >::const_iterator "
1340  << "itr = fHandles.begin();" << std::endl;
1341  source << " std::map< TString, VarHandleBase* >::const_iterator "
1342  << "end = fHandles.end();" << std::endl;
1343  source << " for( ; itr != end; ++itr ) {" << std::endl;
1344  source << " if( ! re.Match( fPrefix + itr->first ) ) continue;"
1345  << std::endl;
1346  source << " if( active ) {" << std::endl;
1347  source << " if( itr->second->IsAvailable() ) "
1348  << "itr->second->SetActive( active );" << std::endl;
1349  source << " } else {" << std::endl;
1350  source << " itr->second->SetActive( active );" << std::endl;
1351  source << " }" << std::endl;
1352  source << " }" << std::endl << std::endl;
1353  source << " return;" << std::endl;
1354  source << " }" << std::endl << std::endl;
1355 
1356  //
1357  // Produce the ReadAllActive(...) function:
1358  //
1359  source << " /**" << std::endl;
1360  source << " * This function can be used to read in all the branches"
1361  << " from the input" << std::endl;
1362  source << " * TTree which are set active for writing out. This can "
1363  << "simplify writing" << std::endl;
1364  source << " * event selector codes immensely. Remember to set the "
1365  << "desired variable" << std::endl;
1366  source << " * active before calling this function." << std::endl;
1367  source << " */" << std::endl;
1368  source << " void " << classname << "::ReadAllActive() {" << std::endl
1369  << std::endl;
1370  source << " // Check if it makes sense to call this function:"
1371  << std::endl;
1372  source << " if( ! fFromInput ) {" << std::endl;
1373  source << " static ::Bool_t wPrinted = kFALSE;" << std::endl;
1374  source << " if( ! wPrinted ) {" << std::endl;
1375  source << " Warning( \"ReadAllActive\", "
1376  << "\"Function only meaningful when used on objects\" );"
1377  << std::endl;
1378  source << " Warning( \"ReadAllActive\", "
1379  << "\"which are used to read information from a D3PD\" );"
1380  << std::endl;
1381  source << " wPrinted = kTRUE;" << std::endl;
1382  source << " }" << std::endl;
1383  source << " }" << std::endl << std::endl;
1384  source << " // Call the base class's function:" << std::endl;
1385  source << " UserD3PDObject::ReadAllActive();" << std::endl
1386  << std::endl;
1387  source << " // Read in the current entry for each active "
1388  << "variable:" << std::endl;
1389  source << " std::map< TString, VarHandleBase* >::const_iterator "
1390  << "itr = fHandles.begin();" << std::endl;
1391  source << " std::map< TString, VarHandleBase* >::const_iterator "
1392  << "end = fHandles.end();" << std::endl;
1393  source << " for( ; itr != end; ++itr ) {" << std::endl;
1394  source << " if( ! itr->second->IsActive() ) continue;"
1395  << std::endl;
1396  source << " itr->second->ReadCurrentEntry();" << std::endl;
1397  source << " }" << std::endl << std::endl;
1398  source << " return;" << std::endl;
1399  source << " }" << std::endl << std::endl;
1400 
1401  //
1402  // Produce the GetStatistics() function:
1403  //
1404  source << " /**" << std::endl;
1405  source << " * This function can be used to get information about "
1406  << "the access" << std::endl;
1407  source << " * pattern/statistics of the job. It should be called "
1408  << "at the end of" << std::endl;
1409  source << " * an analysis job to get the information about the "
1410  << "performance of the" << std::endl;
1411  source << " * analysis." << std::endl;
1412  source << " *" << std::endl;
1413  source << " * @returns An object describing the D3PD access "
1414  << "statistics" << std::endl;
1415  source << " */" << std::endl;
1416  source << " D3PDReadStats " << classname
1417  << "::GetStatistics() const {" << std::endl << std::endl;
1418  source << " // The result object:" << std::endl;
1419  source << " D3PDReadStats result = "
1420  << "UserD3PDObject::GetStatistics();" << std::endl << std::endl;
1421  source << " // Add the statistics from each variable to the "
1422  << "result:" << std::endl;
1423  source << " std::map< ::TString, VarHandleBase* >::const_iterator"
1424  << " itr = fHandles.begin();" << std::endl;
1425  source << " std::map< ::TString, VarHandleBase* >::const_iterator"
1426  << " end = fHandles.end();" << std::endl;
1427  source << " for( ; itr != end; ++itr ) {" << std::endl;
1428  source << " result.AddVariable( itr->second->GetStatistics() );"
1429  << std::endl;
1430  source << " }" << std::endl << std::endl;
1431  source << " return result;" << std::endl;
1432  source << " }" << std::endl << std::endl;
1433 
1434  //
1435  // Produce the Set function:
1436  //
1437  source << " /**" << std::endl;
1438  source << " * This function can be used to copy the contents of the"
1439  << " entire object" << std::endl;
1440  source << " * for a given event. This can be useful for instance "
1441  << "when the user" << std::endl;
1442  source << " * wants to copy all information to an output file, and "
1443  << "modify it a bit," << std::endl;
1444  source << " * and only then write it out." << std::endl;
1445  source << " *" << std::endl;
1446  source << " * @param parent The object to copy the information from"
1447  << std::endl;
1448  source << " * @returns This same object, for convenience reasons"
1449  << std::endl;
1450  source << " */" << std::endl;
1451  source << " " << classname << "& " << classname << "::Set( const "
1452  << classname << "& parent ) {" << std::endl << std::endl;
1453  source << " // Check if this function can be used on the object:"
1454  << std::endl;
1455  source << " if( fFromInput ) {" << std::endl;
1456  source << " Error( \"Set\", "
1457  << "\"Objects used for reading a D3PD can't be modified!\" );"
1458  << std::endl;
1459  source << " return *this;" << std::endl;
1460  source << " }" << std::endl << std::endl;
1461  source << " // Call the base class's function:" << std::endl;
1462  source << " UserD3PDObject::Set( parent );" << std::endl
1463  << std::endl;
1464  std::map< std::string, int > variableCounter;
1465  std::set< ObjectMetadata::Variable >::const_iterator itr =
1466  metadata.variables().begin();
1467  std::set< ObjectMetadata::Variable >::const_iterator end =
1468  metadata.variables().end();
1469  for( ; itr != end; ++itr ) {
1470  std::string postfix = "";
1471  if( variableCounter.find( itr->name() ) == variableCounter.end() ) {
1472  variableCounter[ itr->name() ] = 1;
1473  } else {
1474  postfix =
1475  std::to_string( variableCounter[ itr->name() ] );
1476  variableCounter[ itr->name() ]++;
1477  }
1478  source << " if( parent." << variableName( itr->name() )
1479  << postfix << ".IsAvailable() && "
1480  << variableName( itr->name() ) << postfix
1481  << ".IsActive() ) {" << std::endl;
1482  if( itr->primitive() ) {
1483  source << " " << variableName( itr->name() ) << postfix
1484  << "() = parent." << variableName( itr->name() )
1485  << postfix << "();" << std::endl;
1486  } else {
1487  source << " *( " << variableName( itr->name() )
1488  << postfix << "() ) = *( parent."
1489  << variableName( itr->name() ) << postfix
1490  << "() );" << std::endl;
1491  }
1492  source << " } else {" << std::endl;
1493  if( itr->primitive() ) {
1494  source << " " << variableName( itr->name() )
1495  << postfix << "() = 0;" << std::endl;
1496  } else {
1497  source << " " << variableName( itr->name() )
1498  << postfix << "()->clear();" << std::endl;
1499  }
1500  source << " }" << std::endl;
1501  }
1502  source << std::endl << " return *this;" << std::endl;
1503  source << " }" << std::endl << std::endl;
1504 
1505  if( metadata.container() ) {
1506  //
1507  // Produce the Clear function:
1508  //
1509  source << " /**" << std::endl;
1510  source << " * This function makes it easier to clear out the "
1511  << "object completely." << std::endl;
1512  source << " * It cleares all the vector variables, and sets the "
1513  << "element number" << std::endl;
1514  source << " * variable to 0. Very useful when performing object "
1515  << "selection." << std::endl;
1516  source << " * The option argument is not used at the moment for "
1517  << "anything." << std::endl;
1518  source << " * It's only there because the <code>Clear</code> "
1519  << "function defined in" << std::endl;
1520  source << " * TObject has this parameter as well." << std::endl;
1521  source << " *" << std::endl;
1522  source << " * @param option Ignored at the moment" << std::endl;
1523  source << " */" << std::endl;
1524  source << " void " << classname << "::Clear( Option_t* opt ) {"
1525  << std::endl << std::endl;
1526  source << " // Check if this function can be used on the "
1527  << "object:" << std::endl;
1528  source << " if( fFromInput ) {" << std::endl;
1529  source << " Error( \"Clear\", "
1530  << "\"Objects used for reading a D3PD can't be cleared!\" );"
1531  << std::endl;
1532  source << " return;" << std::endl;
1533  source << " }" << std::endl << std::endl;
1534  source << " // Call the base class's function:" << std::endl;
1535  source << " UserD3PDObject::Clear( opt );" << std::endl
1536  << std::endl;
1537  source << " // Clear each variable:" << std::endl;
1538  source << " std::map< ::TString, VarHandleBase* >::const_iterator"
1539  << " itr = fHandles.begin();" << std::endl;
1540  source << " std::map< ::TString, VarHandleBase* >::const_iterator"
1541  << " end = fHandles.end();" << std::endl;
1542  source << " for( ; itr != end; ++itr ) {" << std::endl;
1543  source << " itr->second->Clear();" << std::endl;
1544  source << " }" << std::endl << std::endl;
1545  source << " return;" << std::endl;
1546  source << " }" << std::endl << std::endl;
1547 
1548  //
1549  // Produce the Add function:
1550  //
1551  source << " /**" << std::endl;
1552  source << " * This function can be used to easily add an "
1553  << "'element' describing one" << std::endl;
1554  source << " * object to an output collection. Comes in very "
1555  << "handy when performing" << std::endl;
1556  source << " * object selection." << std::endl;
1557  source << " *" << std::endl;
1558  source << " * Note that variables which are not available from "
1559  << "the input, will be" << std::endl;
1560  source << " * filled with dummy values." << std::endl;
1561  source << " *" << std::endl;
1562  source << " * @param el The 'element' that should be added to "
1563  << "the collection" << std::endl;
1564  source << " */" << std::endl;
1565  source << " " << classname << "& " << classname << "::Add( const "
1566  << classname << "Element& el ) {" << std::endl << std::endl;
1567  source << " // Check if this function can be used on the "
1568  << "object:" << std::endl;
1569  source << " if( fFromInput ) {" << std::endl;
1570  source << " Error( \"Add\", \"Objects used for reading a "
1571  << "D3PD can't be modified!\" );" << std::endl;
1572  source << " return *this;" << std::endl;
1573  source << " }" << std::endl << std::endl;
1574  source << " // Call the base class's function:" << std::endl;
1575  source << " UserD3PDObject::Add( el );" << std::endl
1576  << std::endl;
1577  variableCounter.clear();
1578  itr = metadata.variables().begin();
1579  end = metadata.variables().end();
1580  for( ; itr != end; ++itr ) {
1581  // Treat the size variable in a special way:
1582  if( itr->name() == "n" ) {
1583  source << " ++( n() );" << std::endl;
1584  continue;
1585  }
1586  if( itr->name() == "N" ) {
1587  source << " ++( N() );" << std::endl;
1588  continue;
1589  }
1590 
1591  // Construct a possible post-fix for the variable name:
1592  std::string postfix = "";
1593  if( variableCounter.find( itr->name() ) ==
1594  variableCounter.end() ) {
1595  variableCounter[ itr->name() ] = 1;
1596  } else {
1597  postfix =
1598  std::to_string( variableCounter[ itr->name() ] );
1599  variableCounter[ itr->name() ]++;
1600  }
1601 
1602  source << " if( el." << variableName( itr->name() )
1603  << postfix << ".IsAvailable() && "
1604  << variableName( itr->name() ) << postfix
1605  << ".IsActive() ) {" << std::endl;
1606  source << " " << variableName( itr->name() ) << postfix
1607  << "()->push_back( el." << variableName( itr->name() )
1608  << postfix << "() );" << std::endl;
1609  source << " } else {" << std::endl;
1610 
1611  // Extract the type of the variable we're dealing with:
1612  bool ok = true;
1613  const std::string type =
1614  vectorTemplateArgument( itr->type(), ok );
1615  if( ! ok ) {
1616  REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR,
1617  "Version2::writeSource" )
1618  << "Unexpected variable type encountered for "
1619  << "container dumper: " << itr->type();
1620  return StatusCode::FAILURE;
1621  }
1622 
1623  // Primitive and complex types have to be treated differently if
1624  // they don't exist in the input:
1625  source << " " << variableName( itr->name() )
1626  << postfix << "()->push_back( ";
1627  if( isPrimitive( type ) ) {
1628  source << "std::numeric_limits< " << type << " >::min()";
1629  } else {
1630  source << type << "()";
1631  }
1632  source << " );" << std::endl;
1633  source << " }" << std::endl;
1634  }
1635  source << " return *this;" << std::endl;
1636  source << " }" << std::endl << std::endl;
1637 
1638  //
1639  // Try to find the size variable's name:
1640  //
1641  static const int NSIZEVARS = 2;
1642  static const char* const SIZEVARS[ NSIZEVARS ] = { "n", "N" };
1643  std::string sizeVariable = "";
1645  for( int i = 0; i < NSIZEVARS; ++i ) {
1646  var.setName( SIZEVARS[ i ] );
1647  if( metadata.variables().find( var ) !=
1648  metadata.variables().end() ) {
1649  sizeVariable = var.name() + "()";
1650  break;
1651  }
1652  }
1653 
1654  //
1655  // Produce the [] operators:
1656  //
1657  source << " /**" << std::endl;
1658  source << " * This operator can be used to get access to one "
1659  << "element in the" << std::endl;
1660  source << " * collection. This element can then be passed around"
1661  << " between parts" << std::endl;
1662  source << " * of the analysis code easily." << std::endl;
1663  source << " *" << std::endl;
1664  source << " * This version is useful when modifying the variable"
1665  << " contents through" << std::endl;
1666  source << " * the proxy objects." << std::endl;
1667  source << " *" << std::endl;
1668  source << " * @param index Index of the element inside the "
1669  << "collection" << std::endl;
1670  source << " */" << std::endl;
1671  source << " " << classname << "Element& " << classname
1672  << "::operator[]( size_t index ) {" << std::endl
1673  << std::endl;
1674  source << " // Check whether the index makes sense:"
1675  << std::endl;
1676  source << " if( index >= static_cast< size_t >( "
1677  << ( sizeVariable == "" ? "1000000" : sizeVariable )
1678  << " ) ) {" << std::endl;
1679  source << " Fatal( \"operator[]\", \"Proxy with index %i"
1680  << " requested\", static_cast< int >( index ) );"
1681  << std::endl;
1682  source << " // The previous should've stopped the code "
1683  << "already," << std::endl;
1684  source << " // but let's go for sure..." << std::endl;
1685  source << " throw std::runtime_error( \"Too large proxy "
1686  << "index\" );" << std::endl;
1687  source << " }" << std::endl << std::endl;
1688  source << " // Make sure that the proxy exists:" << std::endl;
1689  source << " while( fProxies.size() <= index ) {" << std::endl;
1690  source << " fProxies.push_back( new " << classname
1691  << "Element( fProxies.size(), *this ) );" << std::endl;
1692  source << " }" << std::endl;
1693  source << " return *fProxies[ index ];" << std::endl;
1694  source << " }" << std::endl << std::endl;
1695 
1696  source << " /**" << std::endl;
1697  source << " * This operator can be used to get access to one "
1698  << "element in the" << std::endl;
1699  source << " * collection. This element can then be passed around"
1700  << " between parts" << std::endl;
1701  source << " * of the analysis code easily." << std::endl;
1702  source << " *" << std::endl;
1703  source << " * This version is useful when only reading the "
1704  << "variables." << std::endl;
1705  source << " *" << std::endl;
1706  source << " * @param index Index of the element inside the "
1707  << "collection" << std::endl;
1708  source << " */" << std::endl;
1709  source << " const " << classname << "Element& " << classname
1710  << "::operator[]( size_t index ) const {" << std::endl
1711  << std::endl;
1712  source << " // Check whether the index makes sense:"
1713  << std::endl;
1714  source << " if( index >= static_cast< size_t >( "
1715  << ( sizeVariable == "" ? "1000000" : sizeVariable )
1716  << " ) ) {" << std::endl;
1717  source << " Fatal( \"operator[]\", \"Proxy with index %i"
1718  << " requested\", static_cast< int >( index ) );"
1719  << std::endl;
1720  source << " // The previous should've stopped the code "
1721  << "already," << std::endl;
1722  source << " // but let's go for sure..." << std::endl;
1723  source << " throw std::runtime_error( \"Too large proxy "
1724  << "index\" );" << std::endl;
1725  source << " }" << std::endl << std::endl;
1726  source << " // Make sure that the proxy exists:" << std::endl;
1727  source << " while( fProxies.size() <= index ) {" << std::endl;
1728  source << " fProxies.push_back( new " << classname
1729  << "Element( fProxies.size(), *this ) );" << std::endl;
1730  source << " }" << std::endl;
1731  source << " return *fProxies[ index ];" << std::endl;
1732  source << " }" << std::endl << std::endl;
1733 
1734  //
1735  // Produce the += operator:
1736  //
1737  source << " /**" << std::endl;
1738  source << " * A convenience operator for adding an 'element' to "
1739  << "this collection." << std::endl;
1740  source << " *" << std::endl;
1741  source << " * @see Add" << std::endl;
1742  source << " * @param el The 'element' that should be added to "
1743  << "the collection" << std::endl;
1744  source << " */" << std::endl;
1745  source << " " << classname << "& " << classname
1746  << "::operator+=( const " << classname << "Element& el ) {"
1747  << std::endl << std::endl;
1748  source << " return this->Add( el );" << std::endl;
1749  source << " }" << std::endl << std::endl;
1750  }
1751 
1752  //
1753  // Produce the GetVarHandle(...) function:
1754  //
1755  source << " /**" << std::endl;
1756  source << " * This function is used internally to access VarHandle "
1757  << "members" << std::endl;
1758  source << " * by name. This is necessary to push some setup from "
1759  << "compile time" << std::endl;
1760  source << " * to run time. It may sound weird, but it makes a lot "
1761  << "of sense for large" << std::endl;
1762  source << " * classes." << std::endl;
1763  source << " *" << std::endl;
1764  source << " * @param name The name of the C++ variable (not of the "
1765  << "branch)" << std::endl;
1766  source << " * @returns A pointer to the VarHandle object"
1767  << std::endl;
1768  source << " */" << std::endl;
1769  source << " VarHandleBase* " << classname
1770  << "::GetVarHandle( const char* name ) {" << std::endl
1771  << std::endl;
1772  variableCounter.clear();
1773  itr = metadata.variables().begin();
1774  end = metadata.variables().end();
1775  for( ; itr != end; ++itr ) {
1776  // Construct a possible post-fix for the variable name:
1777  std::string postfix = "";
1778  if( variableCounter.find( itr->name() ) ==
1779  variableCounter.end() ) {
1780  variableCounter[ itr->name() ] = 1;
1781  } else {
1782  postfix =
1783  std::to_string( variableCounter[ itr->name() ] );
1784  variableCounter[ itr->name() ]++;
1785  }
1786  if( itr == metadata.variables().begin() ) {
1787  source << " if( ! ::strcmp( name, \""
1788  << variableName( itr->name() ) << postfix << "\" ) ) {"
1789  << std::endl;
1790  } else {
1791  source << " else if( ! ::strcmp( name, \""
1792  << variableName( itr->name() ) << postfix << "\" ) ) {"
1793  << std::endl;
1794  }
1795  source << " return &" << variableName( itr->name() )
1796  << postfix << ";" << std::endl;
1797  source << " }" << std::endl;
1798  }
1799  source << std::endl << " Error( \"GetVarHandle\", \"Variable \\\"%s"
1800  << "\\\" unknown\", name );" << std::endl;
1801  source << " return 0;" << std::endl;
1802  source << " }" << std::endl << std::endl;
1803 
1804  //
1805  // Produce the SetVarHandles(...) function:
1806  //
1807  source << " /**" << std::endl;
1808  source << " * This function is used internally to set up all the "
1809  << "VarHandle members" << std::endl;
1810  source << " * of the class. It speeds up compilation *a lot* to do "
1811  << "this at run-time" << std::endl;
1812  source << " * like this, instead of putting a lot of lines of code "
1813  << "operating on" << std::endl;
1814  source << " * the std::map member." << std::endl;
1815  source << " *" << std::endl;
1816  source << " * @param master Pointer to the master index, or a null "
1817  << "pointer" << std::endl;
1818  source << " */" << std::endl;
1819  source << " void " << classname << "::SetVarHandles( const "
1820  << "::Long64_t* master ) {" << std::endl << std::endl;
1821  source << " // Create a list of variable-branch name pairs:"
1822  << std::endl;
1823  source << " static const Int_t NVARNAMES = "
1824  << metadata.variables().size() << ";" << std::endl;
1825  source << " static const char* VARNAMES[ NVARNAMES ][ 2 ] = {"
1826  << std::endl;
1827  variableCounter.clear();
1828  itr = metadata.variables().begin();
1829  end = metadata.variables().end();
1830  for( ; itr != end; ++itr ) {
1831  // Construct a possible post-fix for the variable name:
1832  std::string postfix = "";
1833  if( variableCounter.find( itr->name() ) ==
1834  variableCounter.end() ) {
1835  variableCounter[ itr->name() ] = 1;
1836  } else {
1837  postfix =
1838  std::to_string( variableCounter[ itr->name() ] );
1839  variableCounter[ itr->name() ]++;
1840  }
1841  // Add the names:
1842  source << " { \"" << variableName( itr->name() ) << postfix
1843  << "\", \"" << variableName( itr->name() ) << "\" }";
1844  if( ++itr != end ) {
1845  source << ",";
1846  }
1847  --itr;
1848  source << std::endl;
1849  }
1850  source << " };" << std::endl << std::endl;
1851  source << " // Set up the fHandles map using this list:"
1852  << std::endl;
1853  source << " for( Int_t i = 0; i < NVARNAMES; ++i ) {"
1854  << std::endl;
1855  source << " VarHandleBase* vh = "
1856  << "GetVarHandle( VARNAMES[ i ][ 0 ] );" << std::endl;
1857  source << " vh->SetName( fPrefix + VARNAMES[ i ][ 1 ] );"
1858  << std::endl;
1859  source << " vh->SetMaster( master );" << std::endl;
1860  source << " fHandles[ VARNAMES[ i ][ 0 ] ] = vh;" << std::endl;
1861  source << " }" << std::endl << std::endl;
1862 
1863  /*
1864  source << " // Access the class's dictionary:" << std::endl;
1865  source << " ::TClass* cl = IsA();" << std::endl;
1866  source << " // Get a list of all members:" << std::endl;
1867  source << " ::TList* members = cl->GetListOfDataMembers();"
1868  << std::endl;
1869  source << " // Set up all the VarHandle members:" << std::endl;
1870  source << " for( ::Int_t i = 0; i < members->GetSize(); ++i ) {"
1871  << std::endl;
1872  source << " // Check that it's a VarHandle:" << std::endl;
1873  source << " ::TDataMember* m = dynamic_cast< ::TDataMember* >("
1874  << " members->At( i ) );" << std::endl;
1875  source << " if( ! m ) {" << std::endl;
1876  source << " Fatal( \"SetVarHandles\", \"Found a wrong "
1877  << "data member\" );" << std::endl;
1878  source << " continue;" << std::endl;
1879  source << " }" << std::endl;
1880  source << " const ::TString type = m->GetTypeName();"
1881  << std::endl;
1882  source << " if( ! type.BeginsWith( \"D3PDReader::VarHandle<\" "
1883  << ") ) {" << std::endl;
1884  source << " continue;" << std::endl;
1885  source << " }" << std::endl;
1886  source << " // If it is, let's set it up:" << std::endl;
1887  source << " VarHandleBase* vh = GetVarHandle( m->GetName() );"
1888  << std::endl;
1889  source << " fHandles[ m->GetName() ] = vh;" << std::endl;
1890  source << " }" << std::endl << std::endl;
1891  source << " // Now configure all variables in a second loop:"
1892  << std::endl;
1893  source << " std::map< TString, VarHandleBase* >::const_iterator "
1894  << "itr = fHandles.begin();" << std::endl;
1895  source << " std::map< TString, VarHandleBase* >::const_iterator "
1896  << "end = fHandles.end();" << std::endl;
1897  source << " for( ; itr != end; ++itr ) {" << std::endl;
1898  source << " itr->second->SetName( fPrefix + itr->first );"
1899  << std::endl;
1900  source << " itr->second->SetMaster( master );" << std::endl;
1901  source << " }" << std::endl << std::endl;
1902  */
1903  source << " return;" << std::endl;
1904  source << " }" << std::endl << std::endl;
1905 
1906  source << "} // namespace D3PDReader" << std::endl;
1907 
1908  source.close();
1909 
1910  return StatusCode::SUCCESS;
1911  }
1912 
1913  StatusCode writeEventHeader( const std::string& classname, const std::string& dir,
1914  const std::set< ObjectMetadata >& metadata ) {
1915 
1916  // Construct the file name:
1917  const std::string fileName = dir + "/" + classname + ".h";
1918 
1919  // If the file already exists, let's not overwrite it:
1920  struct stat fileInfo;
1921  if( ! stat( fileName.c_str(), &fileInfo ) ) return StatusCode::SUCCESS;
1922 
1923  // Let everyone know what we're doing:
1924  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeEventHeader" )
1925  << "Generating file: " << fileName;
1926 
1927  // Open the header file (overwriting a possibly existing file):
1928  std::ofstream header( fileName.c_str() );
1929 
1930  // Write a header for the file:
1931  header << CODE_COMMENT << std::endl;
1932  header << "#ifndef D3PDREADER_" << classname << "_H" << std::endl;
1933  header << "#define D3PDREADER_" << classname << "_H" << std::endl << std::endl;
1934 
1935  //
1936  // Construct the includes:
1937  //
1938  header << "// Local include(s):" << std::endl;
1939  header << "#include \"D3PDObjectBase.h\"" << std::endl;
1940  std::set< std::string > d3pd_reader_names;
1941  std::set< ObjectMetadata >::const_iterator meta_itr = metadata.begin();
1942  std::set< ObjectMetadata >::const_iterator meta_end = metadata.end();
1943  for( ; meta_itr != meta_end; ++meta_itr ) {
1944  // Check if we already included this class:
1946  d3pd_reader_names.insert( meta_itr->name() );
1947  if( ! ret.second ) continue;
1948  // If not, then:
1949  header << "#include \"" << meta_itr->name() << ".h\"" << std::endl;
1950  }
1951  header << std::endl;
1952 
1953  header << "namespace D3PDReader {" << std::endl << std::endl;
1954 
1955  //
1956  // Declare the event class:
1957  //
1958  header << " /**" << std::endl;
1959  header << " * Code generated by CodeGenerator_v2 on:" << std::endl;
1960  header << " * host = " << System::hostName() << std::endl;
1961  header << " * OS = " << System::osName() << " / " << System::osVersion()
1962  << std::endl;
1963  header << " * user = " << System::accountName() << std::endl;
1964  time_t rawtime = time( NULL );
1965  char buf[26];
1966  header << " * time = " << ctime_r( &rawtime, buf );
1967  header << " */" << std::endl;
1968  header << " class " << classname << " : public D3PDObjectBase {" << std::endl
1969  << std::endl;
1970  header << " public:" << std::endl;
1971 
1972  //
1973  // Declare the constructors:
1974  //
1975  header << " /// Default constructor, to be used when reading a D3PD" << std::endl;
1976  header << " " << classname << "();" << std::endl;
1977  header << " /// Constructor for only writing data" << std::endl;
1978  header << " " << classname << "( Bool_t onlyForWriting );" << std::endl
1979  << std::endl;
1980 
1981  //
1982  // Declare some functions:
1983  //
1984  header << " /// Get the currently configured prefix value" << std::endl;
1985  header << " virtual const char* GetPrefix() const;" << std::endl;
1986  header << " /// Set the prefix for the variables" << std::endl;
1987  header << " virtual void SetPrefix( const char* prefix );" << std::endl
1988  << std::endl;
1989 
1990  header << " /// Connect the object to an input TTree" << std::endl;
1991  header << " virtual void ReadFrom( ::TTree* tree );" << std::endl;
1992  header << " /// Connect the object to an output TTree" << std::endl;
1993  header << " virtual void WriteTo( ::TTree* tree );" << std::endl << std::endl;
1994 
1995  header << " /// Turn (selected) branches either on or off" << std::endl;
1996  header << " virtual void SetActive( ::Bool_t active = kTRUE," << std::endl;
1997  header << " const ::TString& pattern = \".*\" );"
1998  << std::endl;
1999  header << " /// Read in all the variables that we need to write out as well"
2000  << std::endl;
2001  header << " virtual void ReadAllActive();" << std::endl << std::endl;
2002  header << " /// Get the D3PD reading statistics" << std::endl;
2003  header << " virtual D3PDReadStats GetStatistics() const;" << std::endl
2004  << std::endl;
2005 
2006  header << " /// Switch the reader object to a new event" << std::endl;
2007  header << " void GetEntry( ::Long64_t entry );" << std::endl << std::endl;
2008 
2009  //
2010  // Declare each object:
2011  //
2012  header << " //" << std::endl;
2013  header << " // All the components of the D3PD:" << std::endl;
2014  header << " //" << std::endl;
2015  FOR_ALL_EVENT_VARIABLES( header << " " << meta_itr->name() << " " << varname
2016  << ";" << std::endl );
2017 
2018  // Declare the additional member variable(s):
2019  header << std::endl << " private:" << std::endl;
2020  header << " Long64_t fEntry; ///< Variable storing the current entry number"
2021  << std::endl;
2022  header << " Bool_t fFromInput; "
2023  << "///< Flag specifying if object is used for D3PD reading"
2024  << std::endl << std::endl;
2025 
2026  // Close the class definition:
2027  header << " ClassDef( " << classname << ", 0 )" << std::endl << std::endl;
2028  header << " }; // class " << classname << std::endl << std::endl;
2029  header << "} // namespace D3PDReader" << std::endl << std::endl;
2030  header << "#endif // D3PDREADER_" << classname << "_H" << std::endl;
2031 
2032  header.close();
2033 
2034  return StatusCode::SUCCESS;
2035  }
2036 
2037  StatusCode writeEventSource( const std::string& classname, const std::string& dir,
2038  const std::set< ObjectMetadata >& metadata ) {
2039 
2040  // Construct the file name:
2041  const std::string fileName = dir + "/" + classname + ".cxx";
2042 
2043  // If the file already exists, let's not overwrite it:
2044  struct stat fileInfo;
2045  if( ! stat( fileName.c_str(), &fileInfo ) ) return StatusCode::SUCCESS;
2046 
2047  // Let everyone know what we're doing:
2048  REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeSource" )
2049  << "Generating file: " << fileName;
2050 
2051  // Open the header file (overwriting a possibly existing file):
2052  std::ofstream source( fileName.c_str() );
2053 
2054  // Add the common header to the file:
2055  source << CODE_COMMENT << std::endl << std::endl;
2056 
2057  // Include the class's header:
2058  source << "#include \"" << classname << ".h\"" << std::endl;
2059  source << "#include \"D3PDPerfStats.h\"" << std::endl << std::endl;
2060 
2061  source << "ClassImp( D3PDReader::" << classname << " )" << std::endl << std::endl;
2062 
2063  source << "namespace D3PDReader {" << std::endl << std::endl;
2064 
2065  //
2066  // Produce the (input) constructor:
2067  //
2068  source << " " << classname << "::" << classname << "()" << std::endl
2069  << " : D3PDObjectBase()," << std::endl;
2070  FOR_ALL_EVENT_VARIABLES( source << " " << varname << "( fEntry, \""
2071  << meta_itr->prefix() << "\" )," << std::endl );
2072  source << " fEntry( 0 )," << std::endl;
2073  source << " fFromInput( kTRUE ) {" << std::endl << std::endl;
2074  source << " }" << std::endl << std::endl;
2075 
2076  //
2077  // Produce the (output) constructor:
2078  //
2079  source << " " << classname << "::" << classname << "( Bool_t )" << std::endl
2080  << " : D3PDObjectBase()," << std::endl;
2081  FOR_ALL_EVENT_VARIABLES( source << " " << varname << "( \""
2082  << meta_itr->prefix() << "\" )," << std::endl );
2083  source << " fEntry( 0 )," << std::endl;
2084  source << " fFromInput( kFALSE ) {" << std::endl << std::endl;
2085  source << " }" << std::endl << std::endl;
2086 
2087  //
2088  // Produce the prefix handling functions:
2089  //
2090  source << " const char* " << classname << "::GetPrefix() const {" << std::endl
2091  << std::endl;
2092  source << " Warning( \"GetPrefix\", \"A prefix is not defined for this object\" );"
2093  << std::endl;
2094  source << " return \"\";" << std::endl;
2095  source << " }" << std::endl << std::endl;
2096 
2097  source << " void " << classname << "::SetPrefix( const char* ) {" << std::endl
2098  << std::endl;
2099  source << " Warning( \"SetPrefix\", \"A prefix is not defined for this object\" );"
2100  << std::endl;
2101  source << " return;" << std::endl;
2102  source << " }" << std::endl << std::endl;
2103 
2104  //
2105  // Produce the ReadFrom(...) function:
2106  //
2107  source << " void " << classname << "::ReadFrom( ::TTree* tree ) {" << std::endl
2108  << std::endl;
2109  source << " if( ! fFromInput ) {" << std::endl;
2110  source << " Error( \"ReadFrom\", \"Object can't read a D3PD. Use a different "
2111  << "constructor!\" );" << std::endl;
2112  source << " return;" << std::endl;
2113  source << " }" << std::endl << std::endl;
2114  FOR_ALL_EVENT_VARIABLES( source << " " << varname << ".ReadFrom( tree );"
2115  << std::endl );
2116  source << std::endl << " return;" << std::endl;
2117  source << " }" << std::endl << std::endl;
2118 
2119  //
2120  // Produce the WriteTo(...) function:
2121  //
2122  source << " void " << classname << "::WriteTo( ::TTree* tree ) {" << std::endl
2123  << std::endl;
2124  FOR_ALL_EVENT_VARIABLES( source << " " << varname << ".WriteTo( tree );"
2125  << std::endl );
2126  source << std::endl << " return;" << std::endl;
2127  source << " }" << std::endl << std::endl;
2128 
2129  //
2130  // Produce the SetActive(...) function:
2131  //
2132  source << " void " << classname << "::SetActive( ::Bool_t active, "
2133  << "const ::TString& pattern ) {" << std::endl << std::endl;
2134  FOR_ALL_EVENT_VARIABLES( source << " " << varname << ".SetActive( "
2135  << "active, pattern );" << std::endl );
2136  source << std::endl << " return;" << std::endl;
2137  source << " }" << std::endl << std::endl;
2138 
2139  //
2140  // Produce the ReadAllActive() function:
2141  //
2142  source << " void " << classname << "::ReadAllActive() {" << std::endl
2143  << std::endl;
2144  FOR_ALL_EVENT_VARIABLES( source << " " << varname << ".ReadAllActive();"
2145  << std::endl );
2146  source << std::endl << " return;" << std::endl;
2147  source << " }" << std::endl << std::endl;
2148 
2149  //
2150  // Produce the GetStatistics() function:
2151  //
2152  source << " D3PDReadStats " << classname << "::GetStatistics() const {"
2153  << std::endl << std::endl;
2154  source << " // The result object:" << std::endl;
2155  source << " D3PDReadStats result( D3PDPerfStats::Instance()->GetStats() );"
2156  << std::endl << std::endl;
2157  source << " // Collect the statistics from all constituents:" << std::endl;
2158  FOR_ALL_EVENT_VARIABLES( source << " result += " << varname
2159  << ".GetStatistics();" << std::endl );
2160  source << std::endl << " return result;" << std::endl;
2161  source << " }" << std::endl << std::endl;
2162 
2163  //
2164  // Produce the GetEntry(...) function:
2165  //
2166  source << " void " << classname << "::GetEntry( ::Long64_t entry ) {" << std::endl
2167  << std::endl;
2168  source << " fEntry = entry;" << std::endl;
2169  source << " return;" << std::endl;
2170  source << " }" << std::endl << std::endl;
2171 
2172  source << "} // namespace D3PDReader" << std::endl;
2173  source.close();
2174 
2175  return StatusCode::SUCCESS;
2176  }
2177 
2178  } // namespace Version2
2179 
2180 } // namespace D3PD
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
beamspotnt.var
var
Definition: bin/beamspotnt.py:1394
D3PD::Version2::writeD3PDPerfStats
StatusCode writeD3PDPerfStats(const std::string &dir)
This function can be used to create the D3PDReader::D3PDPerfStats class's source files.
Definition: CodeGenerator_v2.cxx:528
D3PD::Version2::writeUserD3PDObject
StatusCode writeUserD3PDObject(const std::string &dir)
This function can be used to create the D3PDReader::UserD3PDObject class's source files.
Definition: CodeGenerator_v2.cxx:411
D3PD::Version2::writeSource
StatusCode writeSource(const std::string &classname, const std::string &dir, const ObjectMetadata &metadata)
This function is used to generate the source file of a D3PDReader class.
Definition: CodeGenerator_v2.cxx:967
get_generator_info.result
result
Definition: get_generator_info.py:21
header
Definition: hcg.cxx:526
FOR_ALL_EVENT_VARIABLES
#define FOR_ALL_EVENT_VARIABLES(EXP)
A convenience macro used in the event class generation.
Definition: CodeGenerator_v2.cxx:39
CodeGenerator_v2.h
D3PD::Version2::writeD3PDObjectBase
StatusCode writeD3PDObjectBase(const std::string &dir)
This function can be used to create the D3PDReader::D3PDObjectBase class's source files.
Definition: CodeGenerator_v2.cxx:265
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
ObjectMetadata.h
D3PD::isPrimitive
bool isPrimitive(const std::string &type)
This function is used in the code generator to determine from a type name if it's a primitive type or...
Definition: isPrimitive.cxx:24
D3PD::Version2::writeVarHandle
StatusCode writeVarHandle(const std::string &dir)
This function can be used to create the D3PDReader::VarHandle class's source files.
Definition: CodeGenerator_v2.cxx:298
D3PD::Version2::writeUtils
StatusCode writeUtils(const std::string &dir)
This function can be used to create source files containing some utility functions.
Definition: CodeGenerator_v2.cxx:577
spacer
const std::string spacer
Definition: spacer.h:24
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:93
D3PD::Version2::writeEventSource
StatusCode writeEventSource(const std::string &classname, const std::string &dir, const std::set< ObjectMetadata > &metadata)
Write the source of the main event class describing a D3PD tree.
Definition: CodeGenerator_v2.cxx:2037
isPrimitive.h
python.checkMetadata.metadata
metadata
Definition: checkMetadata.py:175
D3PD
Block filler tool for noisy FEB information.
Definition: CaloCellDetailsFillerTool.cxx:29
FortranAlgorithmOptions.fileName
fileName
Definition: FortranAlgorithmOptions.py:13
lumiFormat.i
int i
Definition: lumiFormat.py:85
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
Amg::transform
Amg::Vector3D transform(Amg::Vector3D &v, Amg::Transform3D &tr)
Transform a point from a Trasformation3D.
Definition: GeoPrimitivesHelpers.h:156
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
beamspotman.stat
stat
Definition: beamspotman.py:266
CodeGenerator_v2_constants.h
beamspotman.dir
string dir
Definition: beamspotman.py:623
REPORT_MESSAGE_WITH_CONTEXT
#define REPORT_MESSAGE_WITH_CONTEXT(LVL, CONTEXT_NAME)
Report a message, with an explicitly specified context name.
Definition: Control/AthenaKernel/AthenaKernel/errorcheck.h:345
D3PD::ObjectMetadata
D3PD variable metadata handling class.
Definition: ObjectMetadata.h:36
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
errorcheck.h
Helpers for checking error return status codes and reporting errors.
D3PD::Version2::writeD3PDReadStats
StatusCode writeD3PDReadStats(const std::string &dir)
This function can be used to create the D3PDReader::D3PDReadStats class's source files.
Definition: CodeGenerator_v2.cxx:478
D3PD::ObjectMetadata::Variable
Internal class keeping track of a single variable.
Definition: ObjectMetadata.h:131
impl
Definition: CaloGPUClusterAndCellDataMonitorOptions.h:46
LArG4AODNtuplePlotter.varname
def varname(hname)
Definition: LArG4AODNtuplePlotter.py:37
CaloSwCorrections.time
def time(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:242
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
D3PD::Version2::writeEventHeader
StatusCode writeEventHeader(const std::string &classname, const std::string &dir, const std::set< ObjectMetadata > &metadata)
Write the header of the main event class describing a D3PD tree.
Definition: CodeGenerator_v2.cxx:1913
copySelective.source
string source
Definition: copySelective.py:32
D3PD::Version2::writeHeader
StatusCode writeHeader(const std::string &classname, const std::string &dir, const ObjectMetadata &metadata)
This function is used to create the header of the class describing a set of D3PD variables.
Definition: CodeGenerator_v2.cxx:632
makeTOC.header
header
Definition: makeTOC.py:28
D3PD::Version2::writeVarProxy
StatusCode writeVarProxy(const std::string &dir)
This function can be used to create the D3PDReader::VarProxy class's source files.
Definition: CodeGenerator_v2.cxx:363
python.compressB64.c
def c
Definition: compressB64.py:93