/* 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_T_VALUE_HPP
#define NMM_T_VALUE_HPP NMM_T_VALUE_HPP

#include "nmm/nmm_prefix.hpp"

#include "Value.hpp"
#include "IValueStream.hpp"
#include "OValueStream.hpp"
#include "ValueFactory.hpp"

#include "nmm/utils/NamedObject.hpp"

// XXX: fw: abstract pointer serialization
#include "TAbstractValueConstructor.hpp"

#include "visibility.hpp"

using namespace std;

namespace NMM {

  /** Template value wrapper.
   * This template class is a wrapper for arbitrary types which adds a Value interface to a value.
   *
   * This wrapper implements memory management for event arguments. If memory management is enabled,
   * and the wrapper is of type INVALUE, the wrapper is deleted if it is released using releaseValue().
   * The memory management mode is optionally serialized along with the wrapped value.
   */
  template<typename T>
  class TValue : public Value {
  public:
    /** Default constructor.
     * This constructor does not initialize the wrapped value.
     *
     * @param mem_mgr Memory management mode
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TValue(MemoryMgm mem_mgr = INOUTVALUE, bool is_mgm_enabled = true)
      : Value(Value::SIMPLE, mem_mgr), __is_mgm_enabled(is_mgm_enabled), __serialize_mgm_type(false)   {}

    /** Constructor.
     *
     * @param value Wrapped value
     * @param mem_mgr Memory management mode
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TValue(const T& value, MemoryMgm mem_mgr = INOUTVALUE, bool is_mgm_enabled = true)
      : Value(Value::SIMPLE, mem_mgr), _value(value), __is_mgm_enabled(is_mgm_enabled), __serialize_mgm_type(false)   {}

    /** Copy constructor.
     *
     * @param v Value to copy from
     */
    TValue(const TValue<T>& v)
      : Value(v), _value(v.getRValue()), __is_mgm_enabled(v.__is_mgm_enabled), __serialize_mgm_type(v.__serialize_mgm_type) {}

    /** Get a copy of the wrapped value.
     *
     * @return A copy of the wrapped value
     */
    inline T  getValue()                              const   { return _value; }

    /** Get a reference to the wrapped value.
     *
     * @return A reference to the wrapped value
     */
    inline  const T& getRValue()                      const   { return _value; }

    /** Get a reference to the wrapped value.
     *
     * @return A reference to the wrapped value
     */
    inline        T& getRValue()                              { return _value; }

    /** Get a pointer to the wrapped value.
     *
     * @return A pointer to the wrapped value
     */
    inline  const T* getPValue()                      const   { return &_value; }

    /** Get a pointer to the wrapped value.
     *
     * @return A pointer to the wrapped value
     */
    inline        T* getPValue()                              { return &_value; }

    /** Check if memory management is enabled.
     *
     * @return @c true if memory management is enabled, @c false otherwise
     */
    inline  bool isMgmEnabled()                       const   { return __is_mgm_enabled; }

    /** Enable or disable memory management.
     *
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    inline void setMgmEnabled(bool is_mgm_enabled)            { __is_mgm_enabled = is_mgm_enabled; }

    /** Set wrapped value.
     *
     * @param new_value Wrapped value
     */
    inline void setValue(const T& new_value)                  { _value = new_value; }

    /** Assign value from an input value stream.
     * This method reads the wrapped value and the memory management mode from an input value stream.
     *
     * @param s An input value stream
     */
    virtual void assignFromStream(IValueStream& s)            { if (s.getCurrentType() == "NULL") s.nextElement();  else { s >> _value; if (s.getCurrentType() == "MemoryMgm") {MemoryMgm mgm; s >> mgm; setMemoryStrategy(mgm);} } }

    /** Create value from an input value stream.
     * This method reads the wrapped value and the memory management mode from an input value stream.
     *
     * @param s An input value stream
     */
    virtual void createFromStream(IValueStream& s)            { if (s.getCurrentType() == "NULL") s.nextElement();  else { s >> _value; if (s.getCurrentType() == "MemoryMgm") {MemoryMgm mgm; s >> mgm; setMemoryStrategy(mgm);} } }

    /** Write value to an output value stream.
     * This method writes the wrapped value and the memory management mode to an output value stream.
     *
     * @param s An output value stream
     */
    virtual void toStream(OValueStream& s)             const  { s << _value; if (__serialize_mgm_type) { s << getMemoryStrategy();} }

    /** Implicit conversion operator.
     *
     * @return The converted value as a new TValue wrapper
     */
    template <class D>
    operator TValue<D>()                                      { return TValue<D>(_value); }

    /** Virtual copy constructor.
     *
     * @return A copy of this object which has the same type
     */
    virtual TValue<T>* copy()                          const  { if (getMemoryStrategy() == INVALUE) return new TValue<T>(*this);  return const_cast<TValue<T>* >(this);}

    /** Assignement operator.
     *
     * @param v TValue wrapper to assign from
     */
    void operator=(const TValue<T>& v)                        { Value::operator=(v);  _value = v.getRValue();}

    /** Release this value.
     * If memory management is enabled, and the memory management mode is INVALUE,
     * this object is destroyed.
     */
    virtual void releaseValue()                        const  { if (getMemoryStrategy() == INVALUE && __is_mgm_enabled) delete this;}

  protected:
    /** Set whether to serialize the memory management mode.
     *
     * @param value @c true to serialize the memory management mode, @c false to not serialize it
     */
    void serializeMgmType (bool value)                        { __serialize_mgm_type = value ;}
  private:
    mutable T _value;               ///< Wrapped value
    bool    __is_mgm_enabled;       ///< Memory management is enabled
    bool    __serialize_mgm_type;   ///< Memory management mode is serialized
  };

  /** Value wrapper for char arrays.
   * This class is a wrapper for type char* which adds a Value interface to a buffer of raw binary data.
   */
  template<>
  class DLLEXPORT TValue<char*> : public Value {
  public:
    /** Default constructor.
     * This constructor creates an empty buffer.
     *
     * @param mem_mgr Memory management mode
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TValue(MemoryMgm mem_mgr = INOUTVALUE, bool is_mgm_enabled = true)
      : Value(Value::SIMPLE, mem_mgr) , _value(0), _size(0), __is_mgm_enabled(is_mgm_enabled), __serialize_mgm_type(false) {}

    /** Constructor.
     * This constructor sets the size and pointer to the buffer containing the binary data.
     * It does not copy the given buffer data. This wrapper only stores a pointer to it.
     * The pointer must stay valid as long as this wrapper refers to it.
     *
     * @param value Buffer of binary data
     * @param size Buffer size
     * @param mem_mgr Memory management mode
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TValue(char* value, nmm_uint32 size, MemoryMgm mem_mgr = INOUTVALUE, bool is_mgm_enabled = true)
      : Value(Value::SIMPLE, mem_mgr), _value(value), _size(size), __is_mgm_enabled(is_mgm_enabled), __serialize_mgm_type(false)  {}

    /** Copy constructor.
     *
     * @param v Value to copy from
     */
    TValue(const TValue<char*>& v)
      : Value(v), _value(v.getRValue()), _size(v.getSize()), __is_mgm_enabled(v.__is_mgm_enabled), __serialize_mgm_type(v.__serialize_mgm_type)  {}

    /** Get the size of the buffer.
     *
     * @return Size of the buffer
     */
    inline nmm_uint32 getSize()                        const   { return _size; }

    /** Get a pointer to the buffer.
     *
     * @return A pointer to the buffer
     */
    inline const char* getValue()                      const   { return _value; }

    /** Get a pointer to the buffer.
     *
     * @return A pointer to the buffer
     */
    inline       char* getValue()                              { return _value; }

    /** Get a reference to the pointer to the buffer.
     *
     * @return A reference to the pointer to the buffer
     */
    inline       char*& getRValue()                            { return _value; }

    /** Get a pointer to the buffer.
     *
     * @return A pointer to the buffer
     */
    inline       char*  getRValue()                    const   { return _value; }

    /** Get a pointer to the pointer to the buffer.
     *
     * @return A pointer to the pointer to the buffer
     */
    inline       char** getPValue()                    const   { return &_value; }

    /** Check if memory management is enabled.
     *
     * @return @c true if memory management is enabled, @c false otherwise
     */
    inline  bool isMgmEnabled()                        const   { return __is_mgm_enabled; }  

    /** Enable or disable memory management.
     *
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    inline void setMgmEnabled(bool is_mgm_enabled)              { __is_mgm_enabled = is_mgm_enabled; }

    /** Set the buffer.
     * This method sets the size and pointer to the buffer containing the binary data.
     * It does not copy the given buffer data. This wrapper only stores a pointer to it.
     * The pointer must stay valid as long as this wrapper refers to it.
     *
     * @param new_value Buffer of binary data
     * @param size Buffer size
     */
    inline void setValue(char* new_value, nmm_uint32 size)     { _value = new_value; _size = size; }

    /** Assign value from an input value stream.
     * This method reads the buffer and the memory management mode from an input value stream.
     *
     * @param s An input value stream
     */
    virtual void assignFromStream(IValueStream& s);

    /** Create value from an input value stream.
     * This method reads the buffer and the memory management mode from an input value stream.
     *
     * @param s An input value stream
     */
    virtual void createFromStream(IValueStream& s);

    /** Write value to an output value stream.
     * This method writes the buffer and the memory management mode to an output value stream.
     *
     * @param s An output value stream
     */
    virtual void toStream(OValueStream& s) const;

    /** Implicit conversion operator.
     *
     * @return The converted value as a new TValue wrapper
     */
    template <class D>
    operator TValue<D>()                                      { return TValue<D>(_value); }

    /** Virtual copy constructor.
     *
     * @return A copy of this object which has the same type
     */
    virtual TValue<char*>* copy()                      const  { if (getMemoryStrategy() == INVALUE) return new TValue<char*>(*this);  return const_cast<TValue<char*>* >(this);}

    /** Assignement operator.
     *
     * @param v TValue wrapper to assign from
     */
    void operator=(const TValue<char*>& v)                    { Value::operator=(v);  _value = v.getRValue();}

    /** Release this value.
     * If memory management is enabled, and the memory management mode is INVALUE,
     * this object is destroyed.
     */
    virtual void releaseValue()                        const  { if (getMemoryStrategy() == INVALUE && __is_mgm_enabled) delete this;}
  protected:
    /** Set whether to serialize the memory management mode.
     *
     * @param value @c true to serialize the memory management mode, @c false to not serialize it
     */
    void serializeMgmType (bool value)                        { __serialize_mgm_type = value ;}
  private:
    mutable char*  _value;          ///< Pointer to buffer
    nmm_uint32 _size;               ///< Size of buffer
    bool    __is_mgm_enabled;       ///< Memory management is enabled
    bool    __serialize_mgm_type;   ///< Memory management mode is serialized
  };
  
  // XXX: fw: abstract pointer serialization
  /** Dynamically instantiate an object.
   * This method instantiates an object of type with the type info and returns a pointer to it
   * which has the given type (template argument). It is used for input serialization of
   * polymorphic pointers.
   *
   * If no TValueConstructor for the requested type is registered at the ValueFactory,
   * this method returns a null pointer
   *
   * @param type Type name of object to instantiate
   * @param ns Type namespace of object to instantiate
   * @return Pointer to created instance or 0
   */
  template<class T>
  T* ValueFactory::createObject(const std::string& type, const std::string& ns) {
    if(type == "NULL") {
      return 0;
    }
  
    /*Begin> Search for a registered constructor */
    ValueConstructor* vc = findValueConstructor(type, ns);
    if(vc) {
      TAbstractValueConstructor<T>* tvc = dynamic_cast< TAbstractValueConstructor<T>* >(vc);
      if(tvc) {
        return tvc->createObject();
      } else {
        ERROR_STREAM("No TValueConstructor for type " << ns << "::" << type << " available" << std::endl);
        return 0;
      }
    } else {
      ERROR_STREAM("No type " << type << " in namespace " << ns << " available " << std::endl);
      return 0;
    }
    /*End< */
  }

  /** Template wrapper for pointer types.
   * This template class is a wrapper for arbitrary pointer types which adds a Value interface to a pointer.
   *
   * This wrapper implements memory management for event arguments. If memory management is enabled,
   * and the wrapper is of type INVALUE, the wrapper is deleted if it is released using releaseValue().
   * The memory management mode is optionally serialized along with the wrapped value.
   */
  template<class T>
  class TValue<T*> : public Value {
  public:
    /** Default constructor.
     * This constructor does not initialize the wrapped value.
     *
     * @param mem_mgr Memory management mode
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TValue(MemoryMgm mem_mgr = INOUTVALUE, bool is_mgm_enabled = true)
      : Value(Value::SIMPLE, mem_mgr), _value(0), __is_mgm_enabled(is_mgm_enabled), __serialize_mgm_type(false) { }

    /** Constructor.
     *
     * @param value Wrapped value
     * @param mem_mgr Memory management mode
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TValue(const T* value, MemoryMgm mem_mgr = INOUTVALUE, bool is_mgm_enabled = true)
      : Value(Value::SIMPLE, mem_mgr), _value(const_cast<T*>(value)), __is_mgm_enabled(is_mgm_enabled), __serialize_mgm_type(false){ }

    /** Copy constructor.
     *
     * @param v Value to copy from
     */
    TValue(const TValue<T*>& v)
      : Value(v), _value(0), __is_mgm_enabled(v.__is_mgm_enabled), __serialize_mgm_type(v.__serialize_mgm_type)  { if (v.getValue() != 0) _value = const_cast<T*>(v.getValue()); }

    /** Destructor.
     */
    ~TValue() { }

    /** Check if this value is of pointer type.
     *
     * @return true
     */
    virtual bool isPointerType()                    const   { return true; }

    /** Get the wrapped pointer.
     *
     * @return The wrapped pointer
     */
    inline const T*  getValue()                     const   { return _value; }

    /** Get the wrapped pointer.
     *
     * @return The wrapped pointer
     */
    inline       T*  getValue()                             { return _value; }

    /** Get a reference to the wrapped pointer.
     *
     * @return A reference to the wrapped pointer
     */
    inline T* const& getRValue()                    const   { return _value; }

    /** Get a reference to the wrapped pointer.
     *
     * @return A reference to the wrapped pointer
     */
    inline       T*& getRValue()                            { return _value; }

    /** Get a pointer to the wrapped pointer.
     *
     * @return a pointer to the wrapped pointer
     */
    inline       T** getPValue()                            { return &_value; }

    /** Get a pointer to the wrapped pointer.
     *
     * @return a pointer to the wrapped pointer
     */
    inline T* const* getPValue()                    const   { return &_value; }

    /** Set the wrapped pointer.
     *
     * @param new_value The wrapped pointer
     */
    inline void setValue(T* new_value)                      { _value = new_value; }

    /** Check if memory management is enabled.
     *
     * @return @c true if memory management is enabled, @c false otherwise
     */
    inline  bool isMgmEnabled()                     const   { return __is_mgm_enabled; }  

    /** Enable or disable memory management.
     *
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    inline void setMgmEnabled(bool is_mgm_enabled)           { __is_mgm_enabled = is_mgm_enabled; }

    /** Assign value from an input value stream.
     * This method reads the wrapped value and the memory management mode from an input value stream.
     * The object the wrapped pointer points to is created dynamically using the Value Factory.
     * If the wrapped pointer already points to an object, no new object is created.
     *
     * @param s An input value stream
     */
    virtual void assignFromStream(IValueStream& s) {
      if (s.getCurrentType() == "NULL") {
        _value = 0;
        s.nextElement();
      } else {
        if (_value) {
          s >> *_value;   //if a value is set we use this one
          if (s.getCurrentType() == "MemoryMgm") { 
            MemoryMgm mgm; s >> mgm; setMemoryStrategy(mgm);
          } 
          return;
        }

        if ( ! SValueFactory::getInstance().isValueAvailable(s.getCurrentTypeInfo()) ) {
          /* Creates a dummy type */
          Value* dummy_value = SValueFactory::getInstance().createValue(s.getCurrentTypeInfo());
          s >> *dummy_value;
          delete dummy_value;
          if (s.getCurrentType() == "MemoryMgm") { 
            MemoryMgm mgm; s >> mgm; setMemoryStrategy(mgm);
          } 
          return;
        }

        Value* tmp_value = 0;

        /* create the instance */
        tmp_value = SValueFactory::getInstance().createValue(s.getCurrentTypeInfo());

        /* cast to the correct type */
        _value = dynamic_cast<T*>(tmp_value);
        
        // XXX: fw: abstract pointer serialization
        //       /* if all fails, create the value using the new Operator. */
        //       if (!_value)
        //         _value = new T();
        if(!_value) {
          _value = SValueFactory::getInstance().template createObject<T>(s.getCurrentTypeInfo());
        }
      
        /* Read the value */
        if (_value!= 0) {
          s >> *_value;
          if (s.getCurrentType() == "MemoryMgm") { 
            MemoryMgm mgm; s >> mgm; setMemoryStrategy(mgm);
          } 
        }
        else {
          GLOBAL_ERROR_STREAM("Runtime error in Value"<< std::endl);
          delete tmp_value;
        }
      }
    }

    /** Create value from an input value stream.
     * This method reads the wrapped value and the memory management mode from an input value stream.
     * The object the wrapped pointer points to is created dynamically using the Value Factory.
     *
     * @param s An input value stream
     */
    virtual void createFromStream(IValueStream& s){
      delete _value;
      if (s.getCurrentType() == "NULL") {
        _value = 0;
        s.nextElement();
      } else {
        if ( ! SValueFactory::getInstance().isValueAvailable(s.getCurrentTypeInfo()) ) {
          /* Creates a dummy type */
          Value* dummy_value = SValueFactory::getInstance().createValue(s.getCurrentTypeInfo());
          s >> *dummy_value;
          if (s.getCurrentType() == "MemoryMgm") { 
            MemoryMgm mgm; s >> mgm; setMemoryStrategy(mgm);
          } 
          delete dummy_value;
          return;
        }

        Value* tmp_value = 0;

        /* create the instance */
        tmp_value = SValueFactory::getInstance().createValue(s.getCurrentTypeInfo());

        /* cast to the correct type */
        _value = dynamic_cast<T*> (tmp_value);
      
        // XXX: fw: temporary removed because it causes problems with serializing pointers to abstract classes
        //       /* Read the value */
        //       if (!_value) {
        //         _value = new T();
        //       }
        if(!_value) {
          _value = SValueFactory::getInstance().template createObject<T>(s.getCurrentTypeInfo());
        }
      
        if (_value!= 0) {
          s >> *_value;        
          if (s.getCurrentType() == "MemoryMgm") { 
            MemoryMgm mgm; s >> mgm; setMemoryStrategy(mgm);
          } 
        }
        else {
          GLOBAL_ERROR_STREAM("Runtime error in Value"<< std::endl);
          delete _value;
        }
      }
    }

    /** Write value to an output value stream.
     * This method writes the wrapped value and the memory management mode to an output value stream.
     *
     * @param s An output value stream
     */
    virtual void toStream(OValueStream& s)             const  {
      if (_value == 0) {
        s.beginType("NULL");
        s.endType();
      } else {
        s << *_value;
        if (__serialize_mgm_type) { s << getMemoryStrategy(); }
      }
    }

    /** Implicit conversion operator.
     *
     * @return The converted value as a new TValue wrapper
     */
    template <class D>
    operator TValue<D>()                                      { return TValue<D>(_value); }

    /** Member access operator.
     *
     * @return The wrapped pointer
     */
    T* operator->()                                           { return _value; }

    /** Virtual copy constructor.
     *
     * @return A copy of this object which has the same type
     */
    virtual TValue<T*>* copy()                         const  { if (getMemoryStrategy() == INVALUE) return new TValue<T*>(*this);  return const_cast< TValue<T*> * >(this);}

    /** Assignement operator.
     * This operator creates a copy of the object the wrapped pointer points to.
     *
     * @param v TValue wrapper to assign from
     */
    void operator=(const T* v)                                { if (v) { Value::operator=(*v); _value = dynamic_cast<T*>(v->copy()); } }

    /** assignement operator
     */
    void operator=(const TValue<T*>& v)                       { Value::operator=(v);  if (v.getValue()) _value = dynamic_cast<T*>(v.getValue()->copy()); else _value = 0; }

    /** Release this value.
     * If memory management is enabled, and the memory management mode is INVALUE,
     * this object is destroyed.
     */
    virtual void releaseValue()                        const  { if (getMemoryStrategy() == INVALUE && __is_mgm_enabled) delete this;}
  protected:
    /** Set whether to serialize the memory management mode.
   *
   * @param value @c true to serialize the memory management mode, @c false to not serialize it
     */
    void serializeMgmType (bool value)                        { __serialize_mgm_type = value ;}

  private:
    mutable T* _value;              ///< Wrapped pointer
    bool    __is_mgm_enabled;       ///< Memory management is enabled
    bool    __serialize_mgm_type;   ///< Memory management mode is serialized
  };

  /** Wrapper for an "out" value.
   * This is a template wrapper for "out" values of an interface method or event.
   * An "out" value has memory management mode OUTVALUE. The memory management mode is serialized.
   */
  template<typename T>
  class TOutValue : public TValue<T> {
  public:
    /** Default constructor.
     * Memory management is enabled, and the wrapped value is not initialized.
     */
    TOutValue()
      : TValue<T>(Value::OUTVALUE)   { this->serializeMgmType(true); }

    /** Constructor.
     *
     * @param value Wrapped value
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TOutValue(const T& value,  bool is_mgm_enabled = true)
      : TValue<T>(value, Value::OUTVALUE, is_mgm_enabled)   {this->serializeMgmType(true);}

  };

  /** Wrapper for a pointer "out" value of pointer type.
   * This is a template wrapper for "out" values of pointer type of an interface method or event.
   * An "out" value has memory management mode OUTVALUE. The memory management mode is serialized.
   */
  template<typename T>
  class TOutValue<T*> : public TValue<T*> {
  public:
    /** Default constructor.
     * Memory management is enabled, and the wrapped value is not initialized.
     */
    TOutValue()
      : TValue<T*>(Value::OUTVALUE)   {this->serializeMgmType(true);}

    /** Constructor.
     *
     * @param value Wrapped value
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TOutValue(const T* value,  bool is_mgm_enabled = true)
      : TValue<T*>(value, Value::OUTVALUE,is_mgm_enabled )   {this->serializeMgmType(true);}
  };

  /** Wrapper for an "in" value.
   * This is a template wrapper for "in" values of an interface method or event.
   * An "in" value has memory management mode INVALUE. The memory management mode is serialized.
   */
  template<typename T>
  class TInValue : public TValue<T> {
  public:
    /** Default constructor.
     * Memory management is enabled, and the wrapped value is not initialized.
     */
    TInValue()
      : TValue<T>(Value::INVALUE)   {this->serializeMgmType(true);}

    /** Constructor.
     *
     * @param value Wrapped value
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TInValue(const T& value, bool is_mgm_enabled = true)
      : TValue<T>(value, Value::INVALUE, is_mgm_enabled)   {this->serializeMgmType(true);}

  };

  /** Wrapper for a pointer "in" value of pointer type.
   * This is a template wrapper for "in" values of pointer type of an interface method or event.
   * An "in" value has memory management mode INVALUE. The memory management mode is serialized.
   */
  template<typename T>
  class TInValue<T*> : public TValue<T*> {
  public:
    /** Default constructor.
     * Memory management is enabled, and the wrapped value is not initialized.
     */
    TInValue()
      : TValue<T*>(Value::INVALUE)   {this->serializeMgmType(true);}

    /** Constructor.
     *
     * @param value Wrapped value
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TInValue(const T* value, bool is_mgm_enabled = true)
      : TValue<T*>(value, Value::INVALUE, is_mgm_enabled)   {this->serializeMgmType(true);}

  };

  /** Wrapper for an "inout" value.
   * This is a template wrapper for "inout" values of an interface method or event.
   * An "inout" value has memory management mode INOUTVALUE. The memory management mode is serialized.
   */
  template<typename T>
  class TInOutValue : public TValue<T> {
  public:
    /** Default constructor.
     * Memory management is enabled, and the wrapped value is not initialized.
     */
    TInOutValue()
      : TValue<T>(Value::INOUTVALUE)   {this->serializeMgmType(true);}

    /** Constructor.
     *
     * @param value Wrapped value
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TInOutValue(const T& value, bool is_mgm_enabled = true)
      : TValue<T>(value, Value::INOUTVALUE, is_mgm_enabled)   {this->serializeMgmType(true);}

  };

  /** Wrapper for a pointer "inout" value of pointer type.
   * This is a template wrapper for "inout" values of pointer type of an interface method or event.
   * An "inout" value has memory management mode INOUTVALUE. The memory management mode is serialized.
   */
  template<typename T>
  class TInOutValue<T*> : public TValue<T*> {
  public:
    /** Default constructor.
     * Memory management is enabled, and the wrapped value is not initialized.
     */
    TInOutValue()
      : TValue<T*>(Value::INOUTVALUE)   {this->serializeMgmType(true);}

    /** Constructor.
     *
     * @param value Wrapped value
     * @param is_mgm_enabled @c true to enable, @c false to disable memory management
     */
    TInOutValue(const T* value, bool is_mgm_enabled = true)
      : TValue<T*>(value, Value::INOUTVALUE, is_mgm_enabled)   {this->serializeMgmType(true);}
  };

}

#include "nmm/nmm_suffix.hpp"

#endif
