/* 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_TS_DESCRIPTION_HPP
#define NMM_TS_DESCRIPTION_HPP NMM_TS_DESCRIPTION_HPP

#include "nmm/nmm_prefix.hpp"

#include "nmm/comm/serialize/SerializedValue.hpp"
#include "nmm/comm/serialize/TValue.hpp"

#include "visibility.hpp"

#include <iosfwd>

namespace NMM {
  
  /** Transport strategy description.
   * This class describes a supported transport strategy.
   */
  class DLLEXPORT TSDescription
    : public SerializedValue
  {
  public:
    /** Interface flags.
     */
    enum Interfaces {
      ITS_ONE_WAY_EVENT_RECEIVER       = (1 << 0), ///< The %TransportStrategy implements %ITSOneWayEventReceiver.
      ITS_ONE_WAY_CEVENT_RECEIVER      = (1 << 1), ///< The %TransportStrategy implements %ITSOneWayCEventReceiver.
      ITS_ONE_WAY_BUFFER_RECEIVER      = (1 << 2), ///< The %TransportStrategy implements %ITSOneWayBufferReceiver.
      ITS_REQUEST_REPLY_EVENT_RECEIVER = (1 << 3), ///< The %TransportStrategy implements %ITSRequestReplyEventReceiver.
      ITS_ONE_WAY_EVENT_SENDER         = (1 << 4), ///< The %TransportStrategy implements %ITSOneWayEventSender.
      ITS_ONE_WAY_CEVENT_SENDER        = (1 << 5), ///< The %TransportStrategy implements %ITSOneWayCEventSender.
      ITS_ONE_WAY_BUFFER_SENDER        = (1 << 6), ///< The %TransportStrategy implements %ITSOneWayBufferSender.
      ITS_REQUEST_REPLY_EVENT_SENDER   = (1 << 7)  ///< The %TransportStrategy implements %ITSRequestReplyEventSender.
    };
    
    /** Capability flags.
     */
    enum Capabilities {
      TS_RELIABLE                 = (1 << 1),      ///< The %TransportStrategy is reliable.
      TS_RELIABLE_CONNECT         = (1 << 2),      ///< The %TransportStrategy supports reliable connection setup.
      TS_PRESERVE_MESSAGE_HEADERS = (1 << 3),      ///< The %TransportStrategy preserves all fields of a message header.
    };
    
    /** This method computes the set of partner interfaces to a set of
     * interfaces. Partner interfaces are:
     * - ITS_ONE_WAY_EVENT_RECEIVER and ITS_ONE_WAY_EVENT_SENDER
     * - ITS_ONE_WAY_CEVENT_RECEIVER and ITS_ONE_WAY_CEVENT_SENDER
     * - ITS_ONE_WAY_BUFFER_RECEIVER and ITS_ONE_WAY_BUFFER_SENDER
     * - ITS_REQUEST_REPLY_EVENT_RECEIVER and ITS_REQUEST_REPLY_EVENT_SENDER
     *
     * @param interfaces interfaces to get partner interfaces to
     * @return set of partner interfaces
     */
    static unsigned int getPartnerInterfaces(unsigned int interfaces) throw();
    
  public:
    /** @name Constructor & Destructor
     */
    //@{
    /** Constructs a %TSDescription with default attribute.
     */
    TSDescription();
    
    /** Constructs a %TSDescription with the given attributes.
     *
     * @param strategy_type Type name of %TransportStrategy
     * @param interfaces A combination of flags which specifies the set of supported interfaces
     * @param capabilities A combination of flags which specifies the set of capabilities
     */
    TSDescription(const std::string& strategy_type, unsigned int interfaces, unsigned int capabilities);
    
    /** Copy constructor.
     *
     * @param ts_desc TSDescription to copy
     */
    TSDescription(const TSDescription& ts_desc);
    
    /** Virtual copy constructor.
     *
     * @return pointer to copy of this TSDescription
     */
    virtual TSDescription* copy() const;
    //@}
    
    /** @name Access to Attributes.
     */
    //@{
    /** This method returns the type name of the %TransportStrategy.
     *
     * @return type name of the %TransportStrategy
     */
    const std::string& getStrategyType() const throw();
    
    /** This method returns the set of supported interfaces as a combination of flags.
     *
     * @return set of supported interfaces as a combination of flags
     */
    unsigned int getInterfaces() const throw();
    
    /** This method returns the set of capabilities as a combination of flags.
     *
     * @return set of capabilities as a combination of flags
     */
    unsigned int getCapabilities() const throw();
    
    /** This method sets the type name of the %TransportStrategy.
     *
     * @param strategy_type type name of the %TransportStrategy to set
     */
    void setStrategyType(const std::string& strategy_type) throw();
    
    /** This method sets the set of supported interfaces as a combination of flags.
     *
     * @param interfaces set of supported interfaces as a combination of flags to set
     */
    void setInterfaces(unsigned int interfaces) throw();
    
    /** This method sets the set of capabilities as a combination of flags.
     *
     * @param capabilities set of capabilities as a combination of flags to set
     */
    void setCapabilities(unsigned int capabilities) throw();
    //@}
    
    /** @name Operators
     */
    //@{
    /** Two transport strategiy description are equal if their
     * strategy type, interfaces and capabilities match.
     */
    bool operator==(const TSDescription& rhs) const throw();
    
    /** Two transport strategiy description are equal if their
     * strategy type, interfaces and capabilities match.
     */
    bool operator!=(const TSDescription& rhs) const throw();
    
    /** Transport strategy description are ordered by strategy type,
     * interface flags and capability flags.
     */
    bool operator<(const TSDescription& rhs) const throw();
    
    /** Transport strategy description are ordered by strategy type,
     * interface flags and capability flags.
     */
    bool operator>(const TSDescription& rhs) const throw();

    /** Transport strategy description are ordered by strategy type,
     * interface flags and capability flags.
     */
    bool operator<=(const TSDescription& rhs) const throw();
    
    /** Transport strategy description are ordered by strategy type,
     * interface flags and capability flags.
     */
    bool operator>=(const TSDescription& rhs) const throw();
    //@}
    
  private:
    /** Register all attributes for serialization/deserialization.
     */
    void registerAttributes();
    
  private:
    TValue<std::string>  __strategy_type;          ///< Type name.
    TValue<nmm_uint32> __interfaces;             ///< Supported interfaces.
    TValue<nmm_uint32> __capabilities;           ///< Capabilities.
  };
  
  DLLEXPORT std::ostream& operator<<(std::ostream& os, const TSDescription& tsd);
  
  /** OValueStream insertion operator.
     * This operator writes list of TSDescriptions to an OValueStream.
     *
     * @param ov OValueStream to write to
     * @param ts_desc_list list of TSDescriptions
     * @return given OValueStream
     */
  DLLEXPORT OValueStream& operator<<(OValueStream& ov, const list<TSDescription>& ts_desc_list);
  
   /** Input extraction operator.
    * This operator reads list of TSDescriptions from an IValueStream.
    *
    * @param iv IValueStream to read from
    * @param ts_desc_list list of TSDescriptions
    * @return given IValueStream
    */
  DLLEXPORT IValueStream& operator>>(IValueStream& iv, list<TSDescription>& ts_desc_list);
  
  
  inline const std::string& TSDescription::getStrategyType() const throw() {
    return __strategy_type.getRValue();
  }
  
  inline unsigned int TSDescription::getInterfaces() const throw() {
    return __interfaces.getValue();
  }
  
  inline unsigned int TSDescription::getCapabilities() const throw() {
    return __capabilities.getValue();
  }
  
  inline void TSDescription::setStrategyType(const std::string& strategy_type) throw() {
    __strategy_type.setValue(strategy_type);
  }
  
  inline void TSDescription::setInterfaces(unsigned int interfaces) throw() {
    __interfaces.setValue(interfaces);
  }
  
  inline void TSDescription::setCapabilities(unsigned int capabilities) throw() {
    __capabilities.setValue(capabilities);
  }
  
  inline bool TSDescription::operator<(const TSDescription& rhs) const throw() {
    /* compare by strategy type */
    if(__strategy_type.getValue() < rhs.__strategy_type.getValue()) {
      return true;
    } else if(rhs.__strategy_type.getValue() < __strategy_type.getValue()) {
      return false;
    }
    
    /* compare by interface flags */
    if(__interfaces.getValue() < rhs.__interfaces.getValue()) {
      return true;
    } else if(rhs.__interfaces.getValue() < __interfaces.getValue()) {
      return false;
    }
    
    /* compare by capability flags */
    if(__capabilities.getValue() < rhs.__capabilities.getValue()) {
      return true;
    } else if(rhs.__capabilities.getValue() < __capabilities.getValue()) {
      return false;
    }
    
    return false;
  }

  inline bool TSDescription::operator<=(const TSDescription& rhs) const throw() {
    /* compare by strategy type */
    if(__strategy_type.getValue() < rhs.__strategy_type.getValue()) {
      return true;
    } else if(rhs.__strategy_type.getValue() < __strategy_type.getValue()) {
      return false;
    }
    
    /* compare by interface flags */
    if(__interfaces.getValue() < rhs.__interfaces.getValue()) {
      return true;
    } else if(rhs.__interfaces.getValue() < __interfaces.getValue()) {
      return false;
    }
    
    /* compare by capability flags */
    if(__capabilities.getValue() < rhs.__capabilities.getValue()) {
      return true;
    } else if(rhs.__capabilities.getValue() < __capabilities.getValue()) {
      return false;
    }
    
    return true;
  }
  
  inline bool TSDescription::operator>(const TSDescription& rhs) const throw() {
    return !(*this <= rhs);
  }
  
  inline bool TSDescription::operator>=(const TSDescription& rhs) const throw() {
    return !(*this < rhs);
  }
  
  inline bool TSDescription::operator==(const TSDescription& rhs) const throw() {
    return __strategy_type.getValue() == rhs.__strategy_type.getValue() &&
      __interfaces.getValue() == rhs.__interfaces.getValue() &&
      __capabilities.getValue() == rhs.__capabilities.getValue();
  }
  
  inline bool TSDescription::operator!=(const TSDescription& rhs) const throw() {
    return !(*this == rhs);
  }
  
};

#include "nmm/nmm_suffix.hpp"

#endif
