/*
-----------------------------------------------------------------------
Copyright: 2010-2015, iMinds-Vision Lab, University of Antwerp
           2014-2015, CWI, Amsterdam
Contact: astra@uantwerpen.be
Website: http://sf.net/projects/astra-toolbox
This file is part of the ASTRA Toolbox.
The ASTRA Toolbox is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
The ASTRA Toolbox is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with the ASTRA Toolbox. If not, see .
-----------------------------------------------------------------------
$Id$
*/
#ifndef _INC_ASTRA_ASTRAOBJECTFACTORY
#define _INC_ASTRA_ASTRAOBJECTFACTORY
#include "Globals.h"
#include "Config.h"
#include "Singleton.h"
#include "Utilities.h"
#include "TypeList.h"
#include "ProjectorTypelist.h"
#include "AlgorithmTypelist.h"
#ifdef ASTRA_PYTHON
#include "PluginAlgorithm.h"
#endif
namespace astra {
/**
 * This class contains functionality to create data objects based on their type or on a configuration object.
 */
template 
class CAstraObjectFactory : public Singleton > {
public:
	/** A default constructor that contains not a single line of code.
	 */
	CAstraObjectFactory();
	/** Destructor.  
	 */
	~CAstraObjectFactory();
	/** Create, but don't initialize, a new object.
	 *
	 * @param _sType Type of the new object.
	 * @return Pointer to a new, uninitialized object.
	 */
	T* create(std::string _sType);
	/** Create and initialize a new object.
	 *
	 * @param _cfg Configuration object to create and initialize a new object.
	 * @return Pointer to a new, initialized projector.
	 */
	T* create(const Config& _cfg);
	/** Find a plugin.
	*
	* @param _sType Name of plugin to find.
	* @return Pointer to a new, uninitialized object, or NULL if not found.
	*/
	T* findPlugin(std::string _sType);
};
//----------------------------------------------------------------------------------------
// Constructor
template 
CAstraObjectFactory::CAstraObjectFactory()
{
}
//----------------------------------------------------------------------------------------
// Destructor
template 
CAstraObjectFactory::~CAstraObjectFactory()
{
}
//----------------------------------------------------------------------------------------
// Hook for finding plugin in registered plugins.
template 
T* CAstraObjectFactory::findPlugin(std::string _sType)
{
	return NULL;
}
//----------------------------------------------------------------------------------------
// Create 
template 
T* CAstraObjectFactory::create(std::string _sType) 
{
	functor_find finder = functor_find();
	finder.tofind = _sType;
	CreateObject::find(finder);
	if (finder.res == NULL) {
		finder.res = findPlugin(_sType);
	}
	return finder.res;
}
//----------------------------------------------------------------------------------------
// Create with XML
template 
T* CAstraObjectFactory::create(const Config& _cfg)
{
	T* object = create(_cfg.self.getAttribute("type"));
	if (object == NULL) return NULL;
	if (object->initialize(_cfg))
		return object;
	delete object;
	return NULL;
}
//----------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------
// Create the necessary Object Managers
/**
 * Class used to create algorithms from a string or a config object
*/
class _AstraExport CAlgorithmFactory : public CAstraObjectFactory {};
#ifdef ASTRA_PYTHON
template <>
inline CAlgorithm* CAstraObjectFactory::findPlugin(std::string _sType)
	{
		CPluginAlgorithmFactory *fac = CPluginAlgorithmFactory::getSingletonPtr();
		return fac->getPlugin(_sType);
	}
#endif
/**
 * Class used to create 2D projectors from a string or a config object
*/
class _AstraExport CProjector2DFactory : public CAstraObjectFactory {};
/**
 * Class used to create 3D projectors from a string or a config object
*/
class _AstraExport CProjector3DFactory : public CAstraObjectFactory {};
} // end namespace
#endif