/* 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_OBJECTDESCRIPTION_HPP
#define NMM_OBJECTDESCRIPTION_HPP

#include "nmm/nmm_prefix.hpp"

#include "messaging/Event.hpp"
#include "messaging/CEvent.hpp"
#include "serialize/SerializedValue.hpp"
#include "serialize/StdValue.hpp"

#include "visibility.hpp"

namespace NMM {

class Interface;
class IValueStream;
class OValueStream;
/** A ObjectDescription describes the capabilities of an object.
  */
class DLLEXPORT ObjectDescription  : public SerializedValue {
public:
/*! @name Constructor & Destructor
  */
//@{
 /** Constructor.
  */
  ObjectDescription();

 /** Constructor specifying object name.
  *
  * @param object_name name of object
  */
  explicit ObjectDescription(const string& object_name);

 /** Destructor.
  */
  ~ObjectDescription();

 /** Copy constructor.
  */
  ObjectDescription(const ObjectDescription& );

 /** Virtual copy constructor.
  *
  * @return pointer to copy of this ObjectDescription
  */
  virtual ObjectDescription* copy() const { return new ObjectDescription(*this); }
//@}

 /** @name set/addParameter-methods
  * Methods to set the parameter inside this description
  */
//@{

 /** Sets the name of object which is described in this ObjectDescription.
  *
  * @param object_name name of this object
  */
  inline void setObjectName       (const string& object_name)     { __object_name.setValue(object_name); }

  /** Sets the name of a library that offers the object.
   *
   * @param library_name library offering this object
   */
  inline void setLibraryName    (const string& library_name)      { __library_name.setValue(library_name); }

 /** Sets a new interface list of supported interfaces. 
  * 
  * The old list is overwritten.
  * @sa addInterface
  *
  * @param interface_list list of interfaces to set
  */
  inline void setInterfaceList(const list<string>& interface_list){ __interface_list.setValue(interface_list); }

 /** Adds an interface to the description.
  *
  * @param iface Interface to add
  */
  void addInterface(const Interface& iface);

 /** Adds an interface to the description.
  *
  * @param interface_type Interface to add
  */
  void addInterface(const string& interface_type);

 /** Sets the additional description based on a key and a corrseponding value(both of type string).
  *
  * This description can be used to describe some additional parameter, like the developer's name
  * or the location of a camera.
  *
  * @param value_map map of additional parameter
  */
  inline void setServiceDescription(const map<string, string>& value_map)  { __service_description.setValue(value_map); }

 /** Adds an additional description based on key and a corrseponding value(both with type string).
  * An additional description can be used to describe some additional parameter, like the developer's name
  * or the location of a camera.
  *
  * @param key key of additional parameter
  * @param value value of additional parameter
  */
  inline void addServiceDescription(const string& key, const string& value) { __service_description.getRValue().insert(pair<string, string>(key, value)); }

 /** Sets the transport strategy that should be used for out of band communication.
  *
  * @param transport_strategy transport strategy to be used for out of band communication
  */
  inline void setTransportStrategy(const string& transport_strategy)        { __transport_strategy.setValue(transport_strategy); }

 /** Sets the location of an object.
  *
  * @param location location of object 
  */
  void setLocation(const string& location);

  /** Sets the port to access the location of an object.
   *
   * @param port port to access location of object
   *
   */
  void setPort(int port);

  /** Location string of an object is ignored.
   */
  void disableLocation();
  
  /** Location string of an object is used.
   */
  void enableLocation();
//@}
  
/** @name getParameter-methods
 * Methods to get the parameter inside this description
 */
//@{
/** Returns the name of the plugin.
 *
 * @return name of the plugin.
 */
  inline const string& getLibraryName()       const   { return __library_name.getRValue(); }
  
  /** Returns the name of an object inside the plugin.
   *
   * @return name of an object inside the plugin
   */
  inline const string& getObjectName()          const   { return __object_name.getRValue(); }
  
  /** This method tests if the given ObjectDescrption is a subset of this one.
   *
   * @param nd ObjectDescription to compare with this one
   * @return true if given ObjectDescrption is a subset of this one
   */
  bool isSubset(const ObjectDescription& nd)    const;
  
  /** Returns a list of supported interfaces.
   *
   * @return list of supported interfaces
   */
  inline const list<string>& getInterfaceList()  const   { return __interface_list.getRValue(); }

  /** Returns the location of the node.
   *
   * @return location of the node
   */
  inline const string&   getLocation()           const   { return __location.getRValue(); }

  /** Returns the location of the node.
   *
   * @return location of the node
   */
  inline       string&   getLocation()                   { return __location.getRValue(); }

  /** Returns the used port.
   *
   * @return used port
   */
  inline int   getPort()                         const   { return __port.getRValue(); }
  
  /** Returns the map with the additional service description.
   *
   * @return map with the additional service description
   */
  inline const map<string, string>& getServiceDescription() const { return __service_description.getRValue(); }

  /** Returns the map with the additional service description.
   *
   * @return map with the additional service description.
   */
  inline       map<string, string>& getServiceDescription()       { return __service_description.getRValue(); }

  /** Returns the transport strategy that should be used for out of band communication.
   *
   * @return transport strategy that should be used for out of band communication
   */
  inline const string& getTransportStrategy()              const { return __transport_strategy.getRValue(); }

  /** Returns the transport strategy that should be used for out of band communication.
   *
   * @return transport strategy that should be used for out of band communication
   */
  inline       string& getTransportStrategy()                    { return __transport_strategy.getRValue(); }

  /** Returns the value of the location-flag.
   *
   * @return true if the location-flag is enabled, false otherwise
   */
  inline       bool&          isLocationEnabled()          { return __location_flag.getRValue(); }
  
  /** Returns the value of the location-flag.
   *
   * @return true if the location-flag is enabled, false otherwise
   */
  inline const bool&          isLocationEnabled()    const { return __location_flag.getRValue(); }
//@}


/** @name Object-Configuration
  * Methods to access the configuration event. Both methods are for internal use only!!
  */
//@{
  /** Returns config event.
   *
   * Returns config event that must be send to a object to get this configuration.
   *
   * @return config event
   */
  inline const CEvent& getConfigEvent()       const   { return __config_event;}
  
  /** Returns config event.
   *
   * Returns config event that must be send to a object to get this configuration.
   *
   * @return config event
   */
  inline       CEvent& getConfigEvent()               { return __config_event;}
//@}

protected:
  CEvent                          __config_event;         ///< stores the Events that must be send to a object to get this configuration.

private:
  /** Registers all attibutes by the base class SerializedValue for serialization/deserialization.
   */
  void registerAttributes();
  
  /** Tests if the interface list in the given ObjectDescription is a subset of this Interface list.
   *
   * @param od ObjectDescription to compare with this one
   * @return true if the interface list in the given ObjectDescription is a subset of this Interface list, false otherwise
   */
  bool isInterfaceSubset(const ObjectDescription& od) const;


private:
  TValue<string>                  __object_name;          ///< stores the typename of a object
  TValue<string>                  __library_name;         ///< stores the library which can create the object
  TValue<list<string> >           __interface_list;       ///< stores the interfaces supported by this object
  TValue<map<string, string> >    __service_description;  ///< stores additional description
  TValue<string>                  __location;             ///< The hostname of the system
  TValue<string>                  __transport_strategy;   ///< stores the transport strategy that should be used for out of band communication
  TValue<nmm_bool>                __location_flag;        ///< indicates, wether the location is ignored by the isSubset method or not.
  TValue<nmm_int32>               __port;                 ///< stores the used port to request the object
};


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

#endif
