/* Network-Integrated Multimedia Middleware (NMM)
 * http://www.motama.com/nmm.html
 *  
 * Copyright (C) 2006-2007
 * Motama GmbH, Saarbruecken, Germany
 * http://www.motama.com
 *  
 * This file is part of NMM. 
 * 
 * NMM 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; only version 2 of the License.      
 * 
 * NMM 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 NMM; if not, write to the Free Software Foundation,    
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#ifndef NMM_NODEFACTORY_HPP
#define NMM_NODEFACTORY_HPP

#include "nmm/nmm_prefix.hpp"

#include "NodeFactoryID.hpp"
#include "FactoryException.hpp"
#include "FactoryTicket.hpp"

#include "nmm/multimedia/FactoryObject.hpp"
#include "nmm/utils/NamedObject.hpp"

#include "visibility.hpp"

namespace NMM {

class Node;
class FactoryObject;
class FactoryException;
class Plugin;

/** This abstract class is a blass class for all NodeFactories used in NMM.
  * A NodeFactory is used to create and deletes Nodes which are reserved by a Registry.
  * This base class defines abstract method to create and destroy nodes. It also implements
  * methods that can be used to manage several NodeFactories. NodeFactories are identified
  * by a NodeFactoryID that stores their class name.
  */
class DLLEXPORT NodeFactory : public NamedObject{
public:
/** @name Constructor & Destructor
  */
//@{
/** Constructor.
  * @param name of the NodeFactory, normally the class name
  * @param parent Pointer of the parent NodeFactory
  */
  NodeFactory(const char* name, NodeFactory* parent = 0);

/** Destructor.
  */
  virtual ~NodeFactory();
//@}

/** @name factory methods
  * These methods can be used to create and destroy Nodes
  */
//@{
/** This method creates a Node from a given FactoryTicket. If the node can not be created for some reason
  * an exception is thrown. The FactoryTicket is creates by a Registry, if the node is reserved. After
  * this method the FactoryTicket is invalid and can not be used again.
  *
  * @param ticket The ticket is created by a registry and allows the maintainer to create the node.
  * @return A refernce to the new Node
  */
  virtual  Node& createNode (const FactoryTicket& ticket)
    throw (const FactoryException& ) = 0;

/** This method releases a node. 
 *
 * The NodeFactory can delete this node or store it for a later use.
 * @param node The node that should be released
 */
  virtual  void  releaseNode (const Node& node)
    throw (const FactoryException& ) = 0;
  //@}
  
  /** @name NodeFactory management
   * These methods are for internal use 
   */
  //@{
  /** This method  returns the NodeFactoryID of the NodeFactory. 
   *
   * This ID contains the name of the NodeFactory
   * which is used to identify the Factory.
   *
   * @return NodeFactoryID
   */
  virtual const NodeFactoryID& getFactoryID() const {return __factory_id;}
  
  /** This method adds a new child NodeFactory.
   *
   * @param factory child NodeFactory to add
   */
  void addNodeFactory(NodeFactory& factory);
  
  /** This method removes a child NodeFactroy.
   *
   * @param factory child NodeFactory to remove
   */
  void removeNodeFactory(NodeFactory& factory);
  
  /** This mehtod searches a NodeFactory for a given NodeFactoryID.
   *
   * @param factory_id The NodeFacotryID of the requested NodeFactory
   * @return pointer to the requested NodeFactory
   */
  NodeFactory* findNodeFactory(const NodeFactoryID& factory_id);

  /** This method returns all children which are registered at this NodeFactory.
   *
   * @return list of children which are registered at this NodeFactory
   */
  const list<NodeFactory*>& getChildList()    const {return __child_list;}
  
  /** This method returns a pointer to the parent NodeFactory.
   *
   * @return pointer to parent NodeFactory
   */
  const NodeFactory* getParent()              const {return __parent;}

  /** This method returns a pointer to the parent NodeFactory.
   *
   * @return pointer to parent NodeFactory
   */
  NodeFactory* getParent()                    {return __parent;}

  /** This method sets the parent NodeFactory.
   *
   * @param factory parent NodeFactory
   */
  void  setParent(NodeFactory* factory);
  //@}

  /** @name Plugin management
   */
  //@{
  /** This method registers a Plugin.
   * 
   * @param plugin plug-in to register
   */
  virtual void registerPlugin(Plugin* plugin) = 0;

  /** This method registers a Plugin.
   * 
   * @param plugin plug-in to register
   */
  virtual void unregisterPlugin(const Plugin* plugin) = 0;
  //@}


protected:

  /** This method sets the valid flag inside a FactoryTicket to false.
   *
   * @param fp FactoryTicket to set invalid
   */
  inline void setTicketInvalid(const FactoryTicket& fp) const  {fp.setValid(false); }


private:

  NodeFactory*        __parent;                 ///< pointer to the parent NodeFactory
  list<NodeFactory*>  __child_list;             ///< list of children NodeFactories
  NodeFactoryID       __factory_id;             ///< The NodeFactoryID with the name of the NodeFactoryID
};

} //end namespace
#include "nmm/nmm_suffix.hpp"

#endif
