//------------------------------------------------------------------------------
//	Copyright (C) 2009, 2010 Humboldt-Universitaet zu Berlin
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.1 of the License, or (at your option) any later version.
//
//	This library 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
//	Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public
//	License along with this library; if not, write to the Free Software
//	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//------------------------------------------------------------------------------

/**
 * @file ServiceProvider.h
 * @author Ronald Kluth
 * @date created at 2009/10/29
 * @brief Declaration of class odemx::protocol::ServiceProvider
 * @sa ServiceProvider.cpp
 * @since 3.0
 */

#ifndef ODEMX_PROTOCOL_SERVICEPROVIDER_INCLUDED
#define ODEMX_PROTOCOL_SERVICEPROVIDER_INCLUDED

#include <odemx/base/Process.h>
#include <odemx/protocol/Pdu.h>

//----------------------------------------------------------forward declarations

namespace odemx {
namespace protocol {

class Layer;
class Sap;

//-----------------------------------------------------------header declarations

/**
 * @brief Abstract base class for service-implementing classes
 * @ingroup protocol
 * @author Ronald Kluth
 * @since 3.0
 * @see odemx::protocol::Sap odemx::protocol::Service odemx::protocol::Entity odemx::protocol::Device
 *
 * A service usually offers a specific functionality to its users. An interface
 * to a service is provided through a so-called service access point (SAP).
 * Users pass service primitives (i.e. commands with data) to the SAP in order
 * to make use of the service. In ODEMx, service provider implementations
 * are the active components in the layers of the protocol stack. Thus
 * they are derived from class Process.
 *
 * Class ServiceProvider provides the basis for the implementation of service
 * providers. The base functionality includes a vector for an arbitrary number
 * of SAPs and a pointer the layer of the stack which holds the service provider.
 *
 * ServiceProvider objects own their SAPs. Their process behavior is defined as
 * waiting state until data is ready at one of the SAPs. As soon as data becomes
 * available, the Process is activated and calls the pure virtual function
 * @c handleInput. Subclasses must define this to specifiy the service
 * implementation.
 */
class ServiceProvider
:	public base::Process
{
public:
	/// Vector type to hold pointers to SAPs
	typedef std::vector< Sap* > SapVec;
	/// Destruction, deletes all Sap objects owned by the ServiceProvider
	virtual ~ServiceProvider();

	/// Set the owning layer of this service provider
	void setLayer( Layer* layer );
	/// Access the layer, may return 0 if the layer is not set
	Layer* getLayer() const;

	/**
	 * @brief Create and add an SAP to the service provider
	 * @param name The name of the SAP to be created
	 * @return Pointer to the SAP of that name
	 *
	 * If the SAP already exists, a warning will be issued and the existing
	 * object returned. Otherwise, a new Object will be created and added
	 * to a vector. If a layer is set, the SAP will also be regstered
	 * with the layer to make it available to the upper and lower layers.
	 */
	Sap* addSap( const std::string& name );

	/**
	 * @brief Remove an SAP from the service provider
	 * @param name The name of the SAP
	 * @return @c true if successful, @c false if not found
	 *
	 * This method removes an SAP from the ServiceProvider and also
	 * from the layer, if one is set.
	 */
	bool removeSap( const std::string& name );

	/// Access any SAP by name, returns 0 if the name was not found
	Sap* getSap( const std::string& name ) const;

	/// Get a list of all SAPs owned by this service provider
	const SapVec& getSaps() const;
	
protected:
	/**
	 * @brief Implement the service functionality
	 * @param sapName The SAP from which input was received
	 * @param pdu The protocol data unit read from the SAP
	 *
	 * This function defines the behavior of a service provider when
	 * a PDU is input through one of its SAPs. Since the name is provided
	 * as argument, the service provider can choose the appropriate action
	 * for the requested service.
	 */
	virtual void handleInput( const std::string& sapName, PduPtr pdu ) = 0;

	/**
	 * @brief Construction
	 *
	 * The constructor automatically activates the process so that its
	 * @c main function gets called as soon as the simulation run starts.
	 */
	ServiceProvider( base::Simulation& sim, const data::Label& label );

	/**
	 * @brief Process behavior definition
	 *
	 * The ServiceProvider enters a wait state until it receives input.
	 * It then calls @c handleInput and returns to the wait state after that
	 * function call returns.
	 */
	virtual int main();

protected:
	/// Stores a pointer to the layer this service provider belongs to
	Layer* layer_;
	/// Stores pointers to all SAPs owned by the service provider
	SapVec saps_;
	/// Stores pointers to the SAP's buffers (subclasses of Memory) for wait-alert
	synchronization::IMemoryVector sapQueues_;
};

} } // namespace odemx::protocol

#endif /* ODEMX_PROTOCOL_SERVICEPROVIDER_INCLUDED */
