/* 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_SERIALIZE_PTR_LIST_HPP
#define NMM_SERIALIZE_PTR_LIST_HPP NMM_SERIALIZE_PTR_LIST_HPP

#include "nmm/nmm_prefix.hpp"

#include "IValueStream.hpp"
#include "OValueStream.hpp"

#include "ValueFactory.hpp"

#include "nmm/utils/NamedObject.hpp"

#include <list>
#include <string>

namespace NMM {

  /** Output serialization of a list of pointers.
   * This is a helper method which writes a list of pointers to serializable objects to an output value stream.
   * It is used for implementing serialization operators for lists of pointers.
   *
   * Usage:
   * @code
   * OValueStream& operator<<(OValueStream& ov, const list<Interface*>& interface_ptr_list) {
   *   return writePtrList<Interface*>(ov, interface_ptr_list, "Interface");
   * }
   * @endcode
   *
   * The operator is not implemented as a template because for each type, type information is needed.
   * The type information of a type list<T*> generated by this method has type name "listptr_TNAME"
   * and type namespace "std" where "TNAME" is the type name of T.
   *
   * @param ov An output value stream
   * @param v_list Reference to variable to be serialized (list of pointers)
   * @param type_name Type name of element type T
   */
  template <typename T>
  OValueStream& writePtrList(OValueStream& ov, const std::list<T>& v_list, const std::string type_name)
  {
    typedef typename std::list<T>::const_iterator ConstIt; //must be declared as a type
    /* Write the TypInfo */
    ov.beginType("listptr_"+type_name, "std");

    /* Write all elements of the list */
    for (ConstIt it = v_list.begin(); it !=  v_list.end(); ++it) {
      if (*it) {
        ov << **it;
      } else {
        GLOBAL_WARNING_STREAM("Serializing NULL-Ptr in writePtrList." << endl);
        ov.beginType("NULL");
        ov.endType();
      }
    }

    ov.endType();
    return ov;
  }

  /** Input serialization of a list of pointers.
   * This is a helper method which reads a list of pointers to serializable objects from an input value stream.
   * It is used for implementing serialization operators for lists of pointers.
   *
   * Usage:
   * @code
   * IValueStream& operator>>(IValueStream& ov, list<Interface*>& interface_ptr_list) {
   *   return readPtrList<Interface*>(ov, interface_ptr_list, "Interface");
   * }
   * @endcode
   *
   * The operator is not implemented as a template because for each type, type information is needed.
   * The type information of a type list<T*> generated by this method has type name "listptr_TNAME"
   * and type namespace "std" where "TNAME" is the type name of T.
   *
   * @param iv An input value stream
   * @param v_list Reference to variable to be serialized (list of pointers)
   * @param type_name Type name of element type T
   */
  template <class T>
  IValueStream& readPtrList(IValueStream& iv, std::list<T>& v_list, const std::string& type_name)
  {
    /* Begin> Type checking */
    if (iv.getCurrentType() != "listptr_"+type_name) {
      GLOBAL_ERROR_STREAM("List> Invalid type assignment" << endl);
      GLOBAL_ERROR_STREAM ("List> Current type : " << iv.getCurrentType() << "                Expected type: " << "listptr_"+type_name << endl);
      GLOBAL_ERROR_STREAM ("List> Current namespace : " << iv.getCurrentNamespace() << "      Expected namespace: " << "std" << endl);
      iv.nextElement();
      return iv;
    }
    /* End< */

    /* Begin> Access internal attributes */
    if (!iv.goDown()) {
      GLOBAL_DEBUG_STREAM("List seems to be empty" << endl);
      iv.nextElement();
      return iv;
    }
    /* End< */

    /* Begin> While the Stream contains elements, read them */
    while(!iv.isEmpty()) {
      Value* tmp = SValueFactory::getInstance().createValue(iv.getCurrentTypeInfo());
      if (!tmp) {
        GLOBAL_ERROR_STREAM("ARRG! In readPtrList" << endl);
        iv.goUp();
        return iv;
      }

      tmp->createFromStream(iv);

      T list_entry = dynamic_cast<T>(tmp);
      if (!list_entry) {
        delete tmp;
      } else {
        v_list.push_back(list_entry);
      }
    }
    /* End< */

    iv.goUp();

    return iv;
  }

}

#include "nmm/nmm_suffix.hpp"

#endif
