https://github.com/JeffersonLab/chroma
Raw File
Tip revision: 9105801d50b5d49ef0746dbc6d53b79ea0f062d1 authored by Balint Joo on 03 November 2017, 20:45:51 UTC
Updated Submodule
Tip revision: 9105801
objfactory.h
// -*- C++ -*-
/*! @file
 * @brief Factory class for objects from XML input
 */

#ifndef __objfact_h__
#define __objfact_h__

#include "chromabase.h"

#include "typeinfo.h"
#include "typelist.h"
#include <map>
#include <exception>


namespace Chroma
{

////////////////////////////////////////////////////////////////////////////////
// class template DefaultFactoryError
// Manages the "Unknown Type" error in an object factory
////////////////////////////////////////////////////////////////////////////////

  template <typename IdentifierType, class AbstractProduct>
  struct DefaultFactoryError
  {
    struct Exception : public std::exception
    {
      const char* what() const throw() { return "Unknown Type"; }
    };
        
    static AbstractProduct* OnUnknownType(const IdentifierType& id)
      {
	throw Exception();
      }
  };

////////////////////////////////////////////////////////////////////////////////
// class template StringFactoryError
// Manages the "Unknown Type" error in an object factory
////////////////////////////////////////////////////////////////////////////////

  template <typename IdentifierType, class AbstractProduct>
  struct StringFactoryError
  {
    static AbstractProduct* OnUnknownType(const IdentifierType& id)
      {
	std::ostringstream os;
	os << "Factory error: unknown identifier: id = " << id << std::endl;
	throw os.str();
      }
  };

////////////////////////////////////////////////////////////////////////////////
// class template NullFactoryError
// Manages the "Unknown Type" error in an object factory
////////////////////////////////////////////////////////////////////////////////

  template <typename IdentifierType, class AbstractProduct>
  struct NullFactoryError
  {
    static AbstractProduct* OnUnknownType(const IdentifierType&)
      {
	return 0;
      }
  };


//! Object factory class
/*! @ingroup actions
 *
 * Supports abstract creation of objects
 */
  template<class AbstractProduct, 
           typename IdentifierType,
           class TList = NullType,
           typename ProductCreator = AbstractProduct* (*)(),
           template<typename, class>
             class FactoryErrorPolicy = DefaultFactoryError>
  class ObjectFactory : public FactoryErrorPolicy<IdentifierType, AbstractProduct>
  {
  public:
    // Handy type definitions for the body type
    typedef TList ParmList;
    typedef typename TL::TypeAtNonStrict<ParmList,0,NullType>::Result  Parm1;
    typedef typename TL::TypeAtNonStrict<ParmList,1,NullType>::Result  Parm2;
    typedef typename TL::TypeAtNonStrict<ParmList,2,NullType>::Result  Parm3;
    typedef typename TL::TypeAtNonStrict<ParmList,3,NullType>::Result  Parm4;
    typedef typename TL::TypeAtNonStrict<ParmList,4,NullType>::Result  Parm5;
    typedef typename TL::TypeAtNonStrict<ParmList,5,NullType>::Result  Parm6;
    typedef typename TL::TypeAtNonStrict<ParmList,6,NullType>::Result  Parm7;
    typedef typename TL::TypeAtNonStrict<ParmList,7,NullType>::Result  Parm8;
    typedef typename TL::TypeAtNonStrict<ParmList,8,NullType>::Result  Parm9;

    // Member functions
    //! Register the object
    /*! 
     * \param id       object id
     * \param creator  the callback function to create the object
     * \return returns true if registration successful
     */
    bool registerObject(const IdentifierType& id, ProductCreator creator)
      {
	return associations_.insert(
	  typename IdToProductMap::value_type(id, creator)).second;
      }
  
    //! Unregister the object
    /*! 
     * \param id       object id
     * \return returns true if object name was registered before
     */
    bool unregisterObject(const IdentifierType& id)
      {
	return associations_.erase(id) == 1;
      }

    //! Create the object
    /*! 
     * \param id       object id
     * \return returns pointer to the object
     */
    AbstractProduct* createObject(const IdentifierType& id)
    {
      typename IdToProductMap::const_iterator i = associations_.find(id);
      if (i == associations_.end()) {
	
	typedef typename IdToProductMap::const_iterator CI;
	QDPIO::cerr << "Couldnt find key " << id << " in the std::map: " << std::endl;
	QDPIO::cerr << "Available Keys are : " << std::endl;
	for( CI j = associations_.begin();
	     j != associations_.end(); j++) {
	  QDPIO::cerr << j->first << std::endl << std::flush;
	}
	
	return this->OnUnknownType(id);
      }
      else {
	return (i->second)();
      }
    }
        
    //! Create the object
    /*! 
     * \param id       object id
     * \param p1       first parameter arg to callback
     * \return returns pointer to the object
     */
    AbstractProduct* createObject(const IdentifierType& id, Parm1 p1)
    {
      typename IdToProductMap::const_iterator i = associations_.find(id);
      if (i == associations_.end()) {
	
	typedef typename IdToProductMap::const_iterator CI;
	QDPIO::cerr << "Couldnt find key " << id << " in the std::map: " << std::endl;
	QDPIO::cerr << "Available Keys are : " << std::endl;
	for( CI j = associations_.begin();
	     j != associations_.end(); j++) {
	  QDPIO::cerr << j->first << std::endl << std::flush;
	}

	return this->OnUnknownType(id);
      }
      else {
	return (i->second)(p1);
      }
    }
        
    AbstractProduct* createObject(const IdentifierType& id, Parm1 p1, Parm2 p2)
    {
      typename IdToProductMap::const_iterator i = associations_.find(id);
      if (i == associations_.end()) {

	typedef typename IdToProductMap::const_iterator CI;
	QDPIO::cerr << "Couldnt find key " << id << " in the std::map: " << std::endl;
	QDPIO::cerr << "Available Keys are : " << std::endl;
	for( CI j = associations_.begin();
	     j != associations_.end(); j++) {
	  QDPIO::cerr << j->first << std::endl << std::flush;
	}
	
	return this->OnUnknownType(id);
      }
      else {
	  return (i->second)(p1, p2);
      }
    }
    
    AbstractProduct* createObject(const IdentifierType& id, Parm1 p1, Parm2 p2, Parm3 p3)
    {
      typename IdToProductMap::const_iterator i = associations_.find(id);
      if (i == associations_.end()) {
	
	typedef typename IdToProductMap::const_iterator CI;
	QDPIO::cerr << "Couldnt find key " << id << " in the std::map: " << std::endl;
	QDPIO::cerr << "Available Keys are : " << std::endl;
	for( CI j = associations_.begin();
	     j != associations_.end(); j++) {
	  QDPIO::cerr << j->first << std::endl << std::flush;
	}
	
	return this->OnUnknownType(id);
      }
      else {
	  return (i->second)(p1, p2, p3);
      }
    }
        
    AbstractProduct* createObject(const IdentifierType& id, Parm1 p1, Parm2 p2, Parm3 p3,
				  Parm4 p4)
    {
      typename IdToProductMap::const_iterator i = associations_.find(id);
      if (i == associations_.end()) {
	
	typedef typename IdToProductMap::const_iterator CI;
	QDPIO::cerr << "Couldnt find key " << id << " in the std::map: " << std::endl;
	QDPIO::cerr << "Available Keys are : " << std::endl;
	for( CI j = associations_.begin();
	     j != associations_.end(); j++) {
	  QDPIO::cerr << j->first << std::endl << std::flush;
	}
	
	return this->OnUnknownType(id);
      }
      else {
	return (i->second)(p1, p2, p3, p4);
      }
    }
        
    AbstractProduct* createObject(const IdentifierType& id, Parm1 p1, Parm2 p2, Parm3 p3,
				  Parm4 p4, Parm5 p5)
    {
      typename IdToProductMap::const_iterator i = associations_.find(id);
      if (i == associations_.end()) {
	
	typedef typename IdToProductMap::const_iterator CI;
	QDPIO::cerr << "Couldnt find key " << id << " in the std::map: " << std::endl;
	QDPIO::cerr << "Available Keys are : " << std::endl;
	for( CI j = associations_.begin();
	     j != associations_.end(); j++) {
	  QDPIO::cerr << j->first << std::endl << std::flush;
	}
	
	return this->OnUnknownType(id);
      }
      else {
	return (i->second)(p1, p2, p3, p4, p5);
      }
    }

    AbstractProduct* createObject(const IdentifierType& id, Parm1 p1, Parm2 p2, Parm3 p3,
				  Parm4 p4, Parm5 p5, Parm6 p6)
    {
      typename IdToProductMap::const_iterator i = associations_.find(id);
      if (i == associations_.end()) {
	
	typedef typename IdToProductMap::const_iterator CI;
	QDPIO::cerr << "Couldnt find key " << id << " in the std::map: " << std::endl;
	QDPIO::cerr << "Available Keys are : " << std::endl;
	for( CI j = associations_.begin();
	     j != associations_.end(); j++) {
	  QDPIO::cerr << j->first << std::endl << std::flush;
	}
	
	return this->OnUnknownType(id);
      }
      else {
	return (i->second)(p1, p2, p3, p4, p5, p6);
      }
    }

    AbstractProduct* createObject(const IdentifierType& id, Parm1 p1, Parm2 p2, Parm3 p3,
				  Parm4 p4, Parm5 p5, Parm6 p6, Parm7 p7)
    {
      typename IdToProductMap::const_iterator i = associations_.find(id);
      if (i == associations_.end()) {
	
	typedef typename IdToProductMap::const_iterator CI;
	QDPIO::cerr << "Couldnt find key " << id << " in the std::map: " << std::endl;
	QDPIO::cerr << "Available Keys are : " << std::endl;
	for( CI j = associations_.begin();
	     j != associations_.end(); j++) {
	  QDPIO::cerr << j->first << std::endl << std::flush;
	}
	
	return this->OnUnknownType(id);
      }
      else {
	return (i->second)(p1, p2, p3, p4, p5, p6, p7);
      }
    }

    AbstractProduct* createObject(const IdentifierType& id, Parm1 p1, Parm2 p2, Parm3 p3,
				  Parm4 p4, Parm5 p5, Parm6 p6, Parm7 p7, Parm8 p8)
    {
      typename IdToProductMap::const_iterator i = associations_.find(id);
      if (i == associations_.end()) {
	
	typedef typename IdToProductMap::const_iterator CI;
	QDPIO::cerr << "Couldnt find key " << id << " in the std::map: " << std::endl;
	QDPIO::cerr << "Available Keys are : " << std::endl;
	for( CI j = associations_.begin();
	     j != associations_.end(); j++) {
	  QDPIO::cerr << j->first << std::endl << std::flush;
	}
	
	return this->OnUnknownType(id);
      }
      else {
	return (i->second)(p1, p2, p3, p4, p5, p6, p7, p8);
      }
    }

  
  private:
    typedef std::map<IdentifierType, ProductCreator> IdToProductMap;
    IdToProductMap associations_;
  };

}   // namespace Chroma

#endif
back to top