#ifndef __BASEPLUGINCONTAINER_H_2004_09_08
#define __BASEPLUGINCONTAINER_H_2004_09_08

#include <qdom.h>

#include <string>
#include <map>


#include "plugincontainer.h"
#include "plugininformer.h"

using namespace std;

namespace NPlugin
{

class IPluginFactory;
class IProvider;

/** Call init() before using the requestPlugin() function. */
class BasePluginContainer : public PluginContainer
{
	typedef map<string, Plugin*> PluginMap;
	/** @brief This maps the plugin names to the corresponding plugins. 
	  * 
	  * If the plugin is not already loaded it maps to 0.*/
	PluginMap _plugins;
	/** @brief This holds the names of all plugins offered.
	  *
	  * This equals keys(_plugins) and is only used for convenience. */
	vector<string> _pluginNames;
	/** The factory which is used to create the plugins. */
	IPluginFactory* _pFactory;
	/** The provider to be used. */
	IProvider* _pProvider;
protected:
	/** This informer used to inform plugin users about changes in the plugins. */
	PluginInformer _pluginInformer;
	/** @brief This adds a new plugin type to the available ones. 
	  *
	  * It should be supported by the plugin factory used. The pointer will 
	  * be set to 0.\n
	  * @pre No plugin with this name must have been added before. 
	  */
	void addPlugin(const string& name);
	/** Returns #_pFactory. */
	IPluginFactory* pluginFactory() const	{ return _pFactory; }
	/** Returns #_pProvider. */
	IProvider* provider() const	{ return _pProvider; }
	/** @brief This deletes all plugins owned by this container.
	  *
	  * The plugin users will be informed about the remove.
	  */
	void unloadAllPlugins();
public:
	/** @brief Constructs a PluginContainer which uses the given factory to create
	  * the plugins.
	  * 
	  * Call init() before using the requestPlugin() function.
	  */
	BasePluginContainer() {}
	virtual ~BasePluginContainer();
	/** @name PluginContainer Interface
	  *
	  * These functions implement the PluginContainer interface.
	  */
	//@{
	// documented in base class
	virtual Plugin* requestPlugin(const string& name);
	// documented in base class
	virtual void releasePlugin(Plugin* pPlugin);
	// documented in base class
	virtual vector<Plugin*> getLoadedPlugins() const;
	// documented in base class
	virtual vector<string> offeredPlugins() const	{ return _pluginNames; }
	/** @brief This makes the plugin container ready for use.
	  * 
	  * @param pProvider sets #_pProvider
 	  * @param pFactory sets #_pFactory
	  */
	virtual bool init(IProvider* pProvider, IPluginFactory* pFactory);
	/** @brief Default implementation for actions, returning an empty list. */
	vector< pair<QString, QAction*> > actions() { return vector< pair<QString, QAction*> >(); };

	
	//@}
	/** @name IXmlStorable interface
	  * 
	  * Implementation of the IXmlStorable interface.
	  * 
	  * Both functions do nothing in the default implementation.
	  */
	//@{
	/** @brief 	Save the data for this object into the given XML tree.
	  *
	  * The implementation for this creates a new element beneath parent with the
	  * name name(NXml::XmlData&, QDomElement). Afterwards it calls 
	  * saveContainerSettigns(NXml::XmlData&, QDomElement) with the created element
	  * as parent. Finally it creates a &lt;SinglePlugin&gt; element for each
	  * loaded plugin. An attribute "name" is added for each &lt;SinglePlugin&gt; element
	  * with the value of the plugins name (Plugin::name()) and saves each plugin in
	  * this element via the Plugin::saveSettings() function.
	  *
	  * @see IXmlStorable::saveSettings() for details how to save.
	  */
	virtual void saveSettings(NXml::XmlData& outData, QDomElement parent) const;
	/** @brief Loads the data for this object from the given XML node.
	  *
	  * The implementation for this creates a new element beneath parent with the
	  * name name(NXml::XmlData&, QDomElement). Afterwards it calls 
	  * saveContainerSettings(NXml::XmlData&, QDomElement) with the created element
	  * as parent. Finally it creates a &lt;SinglePlugin&gt; element for each
	  * loaded plugin. An attribute "name" is added for each &lt;SinglePlugin&gt; element
	  * with the value of the plugins name (Plugin::name()) and saves each plugin in
	  * this element via the Plugin::saveSettings() function.
	  *
	  * @see IXmlStorable::saveSettings() for details how to save.
	  */
	virtual QDomElement loadSettings(const QDomElement source);
	//@}

	/** @brief Saves the settings for the whole container here.
	  *
	  * Overload this function to save settings affecting the container,
	  * individual settings for each plugin are saved in the saveSettigns(NXml::XmlData&, QDomElement).
	  */
	virtual void saveContainerSettings(NXml::XmlData& outData, QDomElement parent) const;
	/** @brief Load the settings for the whole container here.
	  *
	  * Overload this function to load settings affecting the container,
	  * individual settings for each plugin are loaded in the loadSettigns(const QDomElement).
	  */
	virtual QDomElement loadContainerSettings(const QDomElement source);
	/** @name IPluginInformer interface
	  * 
	  * Implementation of the IPluginInformer interface.
	  */
	//@{
	virtual void addPluginUser(IPluginUser* pUser)	{ _pluginInformer.addPluginUser(pUser); }
	virtual void removePluginUser(IPluginUser* pUser)	{ _pluginInformer.removePluginUser(pUser); };
	//@}
};

}	// namespace NPlugin

#endif // __BASEPLUGINCONTAINER_H_2004_09_08

