// file      : xsd/cxx/tree/serialization.hxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : Copyright (c) 2005 Code Synthesis Tools CC
// license   : GNU GPL v2 + exceptions; see accompanying LICENSE file

#ifndef XSD_CXX_TREE_SERIALIZATION_HXX
#define XSD_CXX_TREE_SERIALIZATION_HXX

#include <sstream>

#include <xsd/cxx/xml/dom/elements.hxx>
#include <xsd/cxx/xml/dom/serialization.hxx>

#include <xsd/cxx/tree/types.hxx>

namespace xsd
{
  namespace cxx
  {
    namespace tree
    {
      template <typename C>
      struct list_stream
      {
        list_stream (std::basic_ostringstream<C>& os,
                     xml::dom::element<C> const& parent)
            : os_ (os), parent_ (parent)
        {
        }

        std::basic_ostringstream<C>& os_;
        xml::dom::element<C> const parent_;
      };

      template <typename X, typename C>
      void
      operator<< (xml::dom::element<C>& e, X const& x)
      {
        std::basic_ostringstream<C> os;
        os << x;
        e.value (os.str ());
      }

      template <typename X, typename C>
      void
      operator<< (xml::dom::attribute<C>& a, X const& x)
      {
        std::basic_ostringstream<C> os;
        os << x;
        a.value (os.str ());
      }

      template <typename X, typename C>
      void
      operator<< (list_stream<C>& ls, X const& x)
      {
        ls.os_ << x;
      }


      // Specialization for sequence.
      //

      template <typename C, typename X>
      void
      operator<< (xml::dom::element<C>& e, sequence<X> const& v)
      {
        std::basic_ostringstream<C> os;
        list_stream<C> ls (os, e);

        ls << v;

        e.value (os.str ());
      }

      template <typename C, typename X>
      void
      operator<< (xml::dom::attribute<C>& a, sequence<X> const& v)
      {
        std::basic_ostringstream<C> os;
        list_stream<C> ls (os, a.element ());

        ls << v;

        a.value (os.str ());
      }

      template <typename C, typename X>
      void
      operator<< (list_stream<C>& ls, sequence<X> const& v)
      {
        for (typename sequence<X>::const_iterator
               b (v.begin ()), e (v.end ()), i (b); i != e; ++i)
        {
          if (i != b)
            ls.os_ << C (' ');

          ls << *i;
        }
      }

      // Specialization for fundamental_base.
      //

      template <typename X, typename C>
      void
      operator<< (xml::dom::element<C>& e, fundamental_base<X> const& x)
      {
        e << static_cast<X const&> (x);
      }

      template <typename X, typename C>
      void
      operator<< (xml::dom::attribute<C>& a, fundamental_base<X> const& x)
      {
        a << static_cast<X const&> (x);
      }

      template <typename X, typename C>
      void
      operator<< (list_stream<C>& ls, fundamental_base<X> const& x)
      {
        ls << static_cast<X const&> (x);
      }


      // Specialization for qname_template
      //

      template <typename C>
      void
      operator<< (xml::dom::element<C>& e, qname_template<C> const& x)
      {
        std::basic_ostringstream<C> os;
        os << xml::dom::prefix<C> (x.namespace_ (), e) << C (':')
           << x.name ();
        e.value (os.str ());
      }

      template <typename C>
      void
      operator<< (xml::dom::attribute<C>& a, qname_template<C> const& x)
      {
        std::basic_ostringstream<C> os;
        os << xml::dom::prefix<C> (x.namespace_ (), a.element ()) << C (':')
           << x.name ();
        a.value (os.str ());
      }

      template <typename X, typename C>
      void
      operator<< (list_stream<C>& ls, qname_template<C> const& x)
      {
        ls.os_ << xml::dom::prefix<C> (x.namespace_ (), ls.parent)
               << C (':') << x.name ();
      }
    }
  }
}

#endif  // XSD_CXX_TREE_SERIALIZATION_HXX
