Skip to content
Snippets Groups Projects
Geant4Handle.cpp 6.12 KiB
Newer Older
// $Id: Geant4Setup.cpp 796 2013-10-03 19:19:39Z markus.frank@cern.ch $
//====================================================================
//  AIDA Detector description implementation for LCD
//--------------------------------------------------------------------
//
//  Author     : M.Frank
//
//====================================================================

// Framework include files
#include "DD4hep/LCDD.h"
#include "DD4hep/Plugins.h"
#include "DD4hep/Printout.h"

#include "DDG4/Geant4Handle.h"
#include "DDG4/Geant4Kernel.h"
#include "DDG4/Geant4GeneratorAction.h"
#include "DDG4/Geant4RunAction.h"
#include "DDG4/Geant4EventAction.h"
#include "DDG4/Geant4TrackingAction.h"
#include "DDG4/Geant4SteppingAction.h"
#include "DDG4/Geant4StackingAction.h"
#include "DDG4/Geant4SensDetAction.h"
#include "DDG4/Geant4PhysicsList.h"
#include "DDG4/Geant4ActionPhase.h"


// C/C++ include files
#include <stdexcept>

using namespace std;
using namespace DD4hep;
using namespace DD4hep::Simulation;

template <typename TYPE> static inline TYPE* checked_value(TYPE* p)    {
  if ( p )  {
    return p;
  }
  throw runtime_error(format("Geant4Handle","Attempt to access an invalid object of type:%s!",
			     typeinfoName(typeid(TYPE)).c_str()));
}

template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle() : value(0) 
{
}

template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle(TYPE* typ) : value(typ) 
{
  if ( value ) value->addRef();
}

template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle(Geant4Handle<TYPE>& handle)
: value(0) 
{
  value = handle.get();
  if ( value ) value->addRef();
}

template <typename TYPE> Geant4Handle<TYPE>::Geant4Handle(const Geant4Kernel& kernel,const string& type_name)
: value(0) 
{
  TypeName typ = TypeName::split(type_name);
  Geant4Context* ctxt = kernel.context();
  Geant4Action* object = PluginService::Create<Geant4Action*>(typ.first,ctxt,typ.second);
  if ( !object && typ.first == typ.second )  {
    typ.first = typeinfoName(typeid(TYPE));
    printout(DEBUG,"Geant4Handle<Geant4Sensitive>",
	     "Object factory for %s not found. Try out %s",
	     typ.second.c_str(),typ.first.c_str());
    object = PluginService::Create<Geant4Action*>(typ.first,ctxt,typ.second);
    if ( !object )  {
      size_t idx = typ.first.rfind(':');
      if ( idx != string::npos ) typ.first = string(typ.first.substr(idx+1));
      printout(DEBUG,"Geant4Handle<Geant4Sensitive>",
	       "Try out object factory for %s",typ.first.c_str());
      object = PluginService::Create<Geant4Action*>(typ.first,ctxt,typ.second);
    }
  }
  if ( object )  {
    TYPE* ptr = dynamic_cast<TYPE*>(object);
    if ( ptr )  {
      value = ptr;
      return;
    }
    throw runtime_error(format("Geant4Handle",
			       "Failed to convert object of type %s to handle of type %s!",
			       type_name.c_str(),typeinfoName(typeid(TYPE)).c_str()));
  }
  throw runtime_error(format("Geant4Handle","Failed to create object of type %s!",type_name.c_str()));
}

template <typename TYPE> Geant4Handle<TYPE>::~Geant4Handle()  {
  if ( value ) value->release();
  value = 0;
}

template <typename TYPE> void Geant4Handle<TYPE>::checked_assign(TYPE* p)  {
  if ( value ) value->release();
  value = checked_value(p);
  if ( value ) value->addRef();
}

template <typename TYPE> Property& Geant4Handle<TYPE>::operator[](const string& property_name) const  {
  PropertyManager& pm = checked_value(value)->properties();
  return pm[property_name];
}

template <typename TYPE> Geant4Handle<TYPE>::operator TYPE*() const   {
  return checked_value(value);
}

template <typename TYPE> bool Geant4Handle<TYPE>::operator!() const   {
  return 0 == value;
}

template <typename TYPE> TYPE* Geant4Handle<TYPE>::get() const   {
  return checked_value(value);
}

template <typename TYPE> TYPE* Geant4Handle<TYPE>::operator->() const   {
  return checked_value(value);
}

template <typename TYPE> Geant4Handle<TYPE>& Geant4Handle<TYPE>::operator=(Geant4Handle& handle)  {
  if ( value ) value->release();
  value = handle.get();
  if ( value ) value->addRef();
  return *this;
}

template <typename TYPE> Geant4Handle<TYPE>& Geant4Handle<TYPE>::operator=(TYPE* typ)   {
  if ( value ) value->release();
  value = typ;
  if ( value ) value->addRef();
  return *this;
}

namespace DD4hep {  namespace Simulation   {

    template <> Geant4Handle<Geant4Sensitive>::Geant4Handle(const Geant4Kernel& kernel, const string& type_name, const string& detector)  {
      try  {
	Geant4Context*       ctxt = kernel.context();
	TypeName             typ  = TypeName::split(type_name);
	Geometry::LCDD&      lcdd = kernel.lcdd();
	Geometry::DetElement det  = lcdd.detector(detector);
	Geant4Sensitive* object = PluginService::Create<Geant4Sensitive*>(typ.first,ctxt,typ.second,&det,&lcdd);
	if ( object )  {
	  value = object;
	  return;
	}
      }
      catch(const exception& e)   {
	printout(ERROR,"Geant4Handle<Geant4Sensitive>","Exception: %s",e.what());
      }
      catch(...)   {
	printout(ERROR,"Geant4Handle<Geant4Sensitive>","Exception: Unknown exception");
      }
      throw runtime_error(format("Geant4Handle<Geant4Sensitive>",
				 "Failed to create sensitive object of type %s for detector %s!",
				 type_name.c_str(),detector.c_str()));
    }
  }
}

template class Geant4Handle<Geant4Action>;
template class Geant4Handle<Geant4Filter>;
template class Geant4Handle<Geant4Sensitive>;
template class Geant4Handle<Geant4ActionPhase>;
template class Geant4Handle<Geant4GeneratorAction>;
template class Geant4Handle<Geant4RunAction>;
template class Geant4Handle<Geant4EventAction>;
template class Geant4Handle<Geant4TrackingAction>;
template class Geant4Handle<Geant4SteppingAction>;
template class Geant4Handle<Geant4StackingAction>;
template class Geant4Handle<Geant4PhysicsList>;

template class Geant4Handle<Geant4GeneratorActionSequence>;
template class Geant4Handle<Geant4PhysicsListActionSequence>;
template class Geant4Handle<Geant4RunActionSequence>;
template class Geant4Handle<Geant4EventActionSequence>;
template class Geant4Handle<Geant4TrackingActionSequence>;
template class Geant4Handle<Geant4SteppingActionSequence>;
template class Geant4Handle<Geant4StackingActionSequence>;
template class Geant4Handle<Geant4SensDetActionSequence>;