/* 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_STRATEGY_DESCRIPTION_HPP_
#define _NMM_STRATEGY_DESCRIPTION_HPP_

#include "nmm/nmm_prefix.hpp"

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

#include "visibility.hpp" 

namespace NMM {  

class IValueStream;
class OValueStream;

  
  /** This class describes a TransportStrategy.
   * A strategy is described by its strategy type name and the set of roles that the strategy is used for.
   * If the strategy type is unspecified, then any suitable default strategy will be used.
   * The set of roles must be specified and not be empty. In addition to this, there is a flag which controls
   * whether the strategy is used exclusively for the given roles, i.e. it may not be reused for other roles
   * for which no strategy was specified.
   *
   */
  class DLLEXPORT StrategyDescription
    : public SerializedValue
  {
  public:
    /** @name Constructor & Destructor
     */
    //@{
    /** Default constructor.
     * - The strategy type is empty
     * - The set of roles is empty
     * - The exclusive flag is @c false
     * @param ti TypeInfo for this StrategyDescription
     */
    StrategyDescription(const TypeInfo& ti);
    
    /** Copy constructor.
     * @param other StrategyDescription to be copied
     */
    StrategyDescription(const StrategyDescription& other);
    
    /** Assignment operator.
     * @param other StrategyDescription to assign to this StrategyDescription
     * @return reference to this object
     */
    StrategyDescription& operator=(const StrategyDescription& other);
    
    /** Virtual copy constructor.
     * @return pointer to the instanciated object
     */
    virtual StrategyDescription* copy() const = 0;
    
    /** Virtual destructor.
     */
    virtual ~StrategyDescription();
    //@}
    
    /** @name Access Methods
     */
    //@{
    /** Get strategy type name.
     * @return strategy type name
     */
    inline const string& getStrategyType() const { return __strategy_type.getRValue(); }
    
    /** Get the set of roles. Roles are speciefied as a bitmask of ORed IInstreamCompositeStrategy::TransportRole .
     * @return roles as unsigned int
     */
    inline unsigned int  getRoles()        const { return __roles.getRValue(); }
    
    /** Check exclusive flag. If exclusive flag is set to true, a TransportStrategy is only used for the specified roles 
     * even if it could be used for some other roles. 
     * @return true if exclusive flag is set, false otherwise.
     */
    inline bool          isExclusive()     const { return __is_exclusive.getRValue(); }
    
    /** Get type of input value stream.
     * If the input value stream is given by its type name, this method returns the type name.
     * Otherwise this method returns an empty string.
     * @return typename of input value stream
     */
    inline const string&       getIValueStream()      const { return __i_value_stream.getRValue(); }
    
    /** Get input value stream stack.
     * If the input value stream is given by a IValueStream object, this method returns a pointer to it.
     * Otherwise this method returns 0.
     * @return pointer to input value stream
     */
    inline const IValueStream* getIValueStreamStack() const { return __i_value_stream_stack.getRValue(); }
    
    /** Get input value stream stack.
     * If the input value stream is given by a IValueStream object, this method returns a pointer to it.
     * Otherwise this method returns 0.
     * @return pointer to input value stream
     */
    inline       IValueStream* getIValueStreamStack()       { return __i_value_stream_stack.getRValue(); }
    
    /** Get type of output value stream.
     * If the output value stream is given by its type name, this method returns the type name.
     * Otherwise this method returns an empty string.
     * @return type of output value stream
     */
    inline const string&       getOValueStream()      const { return __o_value_stream.getRValue(); }
    
    /** Get output value stream stack.
     * If the output value stream is given by a OValueStream object, this method returns a pointer to it.
     * Otherwise this method returns 0.
     * @return pointer to output value stream
     */
    inline const OValueStream* getOValueStreamStack() const { return __o_value_stream_stack.getRValue(); }
    
    /** Get output value stream stack.
     * If the output value stream is given by a OValueStream object, this method returns a pointer to it.
     * Otherwise this method returns 0.
     * @return pointer to output value stream
     */
    inline       OValueStream* getOValueStreamStack()       { return __o_value_stream_stack.getRValue(); }
    
    /** Set strategy type name.
     * @param strategy_type strategy type name
     */
    inline void setStrategyType(const string& strategy_type) { __strategy_type.setValue(strategy_type); }
    
    /** Set the set of roles. Roles are speciefied as a bitmask of ORed IInstreamCompositeStrategy::TransportRole .
     * @param roles set of roles
     */
    inline void setRoles       (unsigned int roles)          { __roles.setValue(roles); }
    
    /** Set exclusive flag. If exclusive flag is set to true, a TransportStrategy is only used for the specified roles 
     * even if it could be used for some other roles. 
     * @param is_exclusive value to set for exclusive flag
     */
    inline void setExclusive   (bool is_exclusive)           { __is_exclusive.setValue(is_exclusive); }
    
    /** Set input value stream type.
     * This method sets the input value stream by a type name.
     * If this description previously contained an IValueStream object, it is deleted.
     * @param i_value_stream input value stream type
     */
    void setIValueStream(const string& i_value_stream);
    
    /** Set output value stream type.
     * This method sets the output value stream by a type name.
     * If this description previously contained an OValueStream object, it is deleted.
     * @param o_value_stream output value stream type
     */
    void setOValueStream(const string& o_value_stream);
    
    /** Set input value stream stack.
     * This method sets a stack of input value streams by the top IValueStream object. A copy of the given object including all 
     * additional IValueStreams of the IValueStream stack is stored internally in this description. In this case the input 
     * value stream type is not used to create the IValueStream and set to an empty string.
     * @param i_value_stream pointer to input value stream
     */
    void setIValueStreamStack(const IValueStream* i_value_stream);
    
    /** Set output value stream stack.
     * This method sets a stack of output value streams by the top OValueStream object. A copy of the given object including all
     * additional OValueStreams of the OValueStream stack is stored internally in this description. In this case the output value stream 
     * type is not used and set to an empty string.
     * @param o_value_stream pointer to output value stream
     */
    void setOValueStreamStack(const OValueStream* o_value_stream);
    //@}
    
  private:
    /** Register attributes for serialization/deserialization.
     */
    void registerAttributes();
    
  private:
    TValue<string>        __strategy_type;           ///< Type of strategy
    TValue<nmm_uint32>  __roles;                   ///< Set of roles that strategy is used for
    TValue<nmm_bool>          __is_exclusive;            ///< Use strategy exclusively for the given roles
    TValue<string>        __i_value_stream;          ///< Input value stream type
    TValue<IValueStream*> __i_value_stream_stack;    ///< Input value stream stack
    TValue<string>        __o_value_stream;          ///< Output value stream type
    TValue<OValueStream*> __o_value_stream_stack;    ///< Output value stream stack
  };
}
#include "nmm/nmm_suffix.hpp"

#endif
