// file      : xsd/cxx/tree/types.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_TYPES_HXX
#define XSD_CXX_TREE_TYPES_HXX

#include <cstdlib> // std::size_t
#include <string>
#include <vector>
#include <ostream> // std::basic_ostream

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

namespace xsd
{
  namespace cxx
  {
    namespace tree
    {
      // string
      //
      template <typename C>
      class string_template: public std::basic_string<C>,
                             public type

      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        string_template ()
        {
        }

        string_template (C* s)
            : base_type (s)
        {
        }

        string_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        string_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        string_template (primary_type const& str)
            : base_type (str)
        {
        }

        string_template (primary_type const& str,
                         std::size_t pos,
                         std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        string_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        string_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        string_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        string_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        string_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // normalized_string: string
      //
      template <typename C>
      class normalized_string_template: public string_template<C>
      {
      protected:
        typedef string_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        normalized_string_template ()
        {
        }

        normalized_string_template (C* s)
            : base_type (s)
        {
        }

        normalized_string_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        normalized_string_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        normalized_string_template (primary_type const& str)
            : base_type (str)
        {
        }

        normalized_string_template (primary_type const& str,
                                    std::size_t pos,
                                    std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        normalized_string_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        normalized_string_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        normalized_string_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        normalized_string_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        normalized_string_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // token: normalized_string
      //
      template <typename C>
      class token_template: public normalized_string_template<C>
      {
      protected:
        typedef normalized_string_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        token_template ()
        {
        }

        token_template (C* s)
            : base_type (s)
        {
        }

        token_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        token_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        token_template (primary_type const& str)
            : base_type (str)
        {
        }

        token_template (primary_type const& str,
                        std::size_t pos,
                        std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        token_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        token_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        token_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        token_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        token_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // nmtoken: token
      //
      template <typename C>
      class nmtoken_template: public token_template<C>
      {
      protected:
        typedef token_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        nmtoken_template ()
        {
        }

        nmtoken_template (C* s)
            : base_type (s)
        {
        }

        nmtoken_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        nmtoken_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        nmtoken_template (primary_type const& str)
            : base_type (str)
        {
        }

        nmtoken_template (primary_type const& str,
                          std::size_t pos,
                          std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        nmtoken_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        nmtoken_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        nmtoken_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        nmtoken_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        nmtoken_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // nmtokens: vector<nmtoken>
      //
      template <typename C>
      class nmtokens_template: public vector<nmtoken_template<C> >
      {
      public:
        nmtokens_template (xml::element<C> const& e)
        {
          parse (e.value ());
        }

        nmtokens_template (xml::attribute<C> const& a)
        {
          parse (a.value ());
        }

      private:
        void
        parse (std::basic_string<C> const& str)
        {
          // Note that according to the spec the separator is exactly
          // one space (0x20). This makes our life much easier.
          //

          for (std::size_t i (0), j (str.find (C (' ')));;)
          {
            if (j != std::basic_string<C>::npos)
            {
              push_back (nmtoken_template<C> (str, i, j - i));
              i = j + 1;
              j = str.find (C (' '), i);
            }
            else
            {
              // Last element.
              push_back (nmtoken_template<C> (str, i));
              break;
            }
          }
        }
      };

      template <typename C>
      inline
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, nmtokens_template<C> const& t)
      {
        for (typename nmtokens_template<C>::const_iterator
               b (t.begin ()), e (t.end ()), i (b); i != e; ++i)
        {
          if (i != b)
            os << C (' ');

          os << *i;
        }

        return os;
      }


      // name: token
      //
      template <typename C>
      class name_template: public token_template<C>
      {
      protected:
        typedef token_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        name_template ()
        {
        }

        name_template (C* s)
            : base_type (s)
        {
        }

        name_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        name_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        name_template (primary_type const& str)
            : base_type (str)
        {
        }

        name_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        name_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        name_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        name_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        name_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        name_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // ncname: name
      //
      template <typename C>
      class ncname_template: public name_template<C>
      {
      protected:
        typedef name_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        ncname_template ()
        {
        }

        ncname_template (C* s)
            : base_type (s)
        {
        }

        ncname_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        ncname_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        ncname_template (primary_type const& str)
            : base_type (str)
        {
        }

        ncname_template (primary_type const& str,
                         std::size_t pos,
                         std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        ncname_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        ncname_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        ncname_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        ncname_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        ncname_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // language: token
      //
      template <typename C>
      class language_template: public token_template<C>
      {
      protected:
        typedef token_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        language_template ()
        {
        }

        language_template (C* s)
            : base_type (s)
        {
        }

        language_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        language_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        language_template (primary_type const& str)
            : base_type (str)
        {
        }

        language_template (primary_type const& str,
                           std::size_t pos,
                           std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        language_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        language_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        language_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        language_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        language_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      //
      //
      template <typename C>
      struct identity_impl: identity
      {
        identity_impl (ncname_template<C> const& id)
            : id_ (id)
        {
        }

        virtual bool
        before (identity const& y) const
        {
          return id_ < dynamic_cast<identity_impl const&> (y).id_;
        }

        virtual void
        throw_duplicate_id () const
        {
          throw duplicate_id<C> (id_);
        }

      private:
        ncname_template<C> const& id_;
      };


      // id: ncname
      //
      template <typename C>
      class id_template: public ncname_template<C>
      {
      protected:
        typedef ncname_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;
        using base_type::empty;

      public:
        ~id_template()
        {
          unregister_id ();
        }

      public:
        id_template ()
            : identity_ (*this)
        {
        }

        id_template (C* s)
            : base_type (s), identity_ (*this)
        {
        }

        id_template (C* s, std::size_t n)
            : base_type (s, n), identity_ (*this)
        {
        }

        id_template (std::size_t n, C c)
            : base_type (n, c), identity_ (*this)
        {
        }

        id_template (primary_type const& str)
            : base_type (str), identity_ (*this)
        {
        }

        id_template (primary_type const& str,
                     std::size_t pos,
                     std::size_t n = npos)
            : base_type (str, pos, n), identity_ (*this)
        {
        }

      public:
        id_template (id_template const& str)
            : base_type (str), identity_ (*this)
        {
        }

      public:
        id_template (xml::element<C> const& e)
            : base_type (e.value ()), identity_ (*this)
        {
        }

        id_template (xml::attribute<C> const& a)
            : base_type (a.value ()), identity_ (*this)
        {
        }

      public:
        id_template&
        operator= (C c)
        {
          unregister_id ();
          base () = c;
          register_id ();

          return *this;
        }

        id_template&
        operator= (C* s)
        {
          unregister_id ();
          base () = s;
          register_id ();

          return *this;
        }

        id_template&
        operator= (primary_type const& str)
        {
          unregister_id ();
          base () = str;
          register_id ();

          return *this;
        }

        id_template&
        operator= (id_template const& str)
        {
          unregister_id ();
          base () = str;
          register_id ();

          return *this;
        }

      public:
        using base_type::container;
        using base_type::root;

        virtual void
        container (type* i)
        {
          unregister_id ();

          type::container (i);

          register_id ();
        }

      private:
        void
        register_id ()
        {
          if (container () != this && !empty ())
          {
            //std::wcerr << "registering " << container ()
            //           << " as '" << *this
            //           << "' on " << container () << std::endl;
            container ()->register_id (identity_, container ());
          }
        }

        void
        unregister_id ()
        {
          if (container () != this && !empty ())
          {
            //std::wcerr << "un-registering " << container ()
            //           << " as '" << *this
            //           << "' on " << container () << std::endl;
            container ()->unregister_id (identity_);
          }
        }

      private:
        identity_impl<C> identity_;
      };


      //
      //
      struct idref_base
      {
        virtual
        ~idref_base ()
        {
        }

        virtual type const*
        get () const = 0;

        virtual type*
        get () = 0;
      };


      // idref: ncname
      //
      template <typename C>
      class idref_template: public ncname_template<C>, public idref_base
      {
      protected:
        typedef ncname_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;
        using base_type::empty;

        using base_type::root;
        using base_type::container;

      public:
        idref_template ()
            : identity_ (*this)
        {
        }

        idref_template (C* s)
            : base_type (s), identity_ (*this)
        {
        }

        idref_template (C* s, std::size_t n)
            : base_type (s, n), identity_ (*this)
        {
        }

        idref_template (std::size_t n, C c)
            : base_type (n, c), identity_ (*this)
        {
        }

        idref_template (primary_type const& str)
            : base_type (str), identity_ (*this)
        {
        }

        idref_template (primary_type const& str,
                        std::size_t pos,
                        std::size_t n = npos)
            : base_type (str, pos, n), identity_ (*this)
        {
        }

      public:
        idref_template (idref_template const& str)
            : base_type (str),
              idref_base (),    // gcc warning
              identity_ (*this)
        {
        }

      public:
        idref_template (xml::element<C> const& e)
            : base_type (e.value ()), identity_ (*this)
        {
        }

        idref_template (xml::attribute<C> const& a)
            : base_type (a.value ()), identity_ (*this)
        {
        }

      public:
        idref_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        idref_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        idref_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        idref_template&
        operator= (idref_template const& str)
        {
          base () = str;
          return *this;
        }

      public:
        type const*
        operator-> () const
        {
          return get ();
        }

        type*
        operator-> ()
        {
          return get ();
        }

        type const&
        operator* () const
        {
          return *(get ());
        }

        type&
        operator* ()
        {
          return *(get ());
        }

        virtual type const*
        get () const
        {
          if (!empty () && container () != this)
          {
            return root ()->lookup_id (identity_);
          }
          else
            return 0;
        }

        virtual type*
        get ()
        {
          if (!empty () && container () != this)
          {
            return root ()->lookup_id (identity_);
          }
          else
            return 0;
        }

        // conversion to bool
        //
        typedef void (idref_template::*bool_convertible)();

        operator bool_convertible () const
        {
          return get () ? &idref_template::true_ : 0;
        }

      private:
        void
        true_ ()
        {
        }

      private:
        identity_impl<C> identity_;
      };


      // idrefs: vector<idref>
      //
      template <typename C>
      class idrefs_template: public vector<idref_template<C> >
      {
      public:
        idrefs_template (xml::element<C> const& e)
        {
          parse (e.value ());
        }

        idrefs_template (xml::attribute<C> const& a)
        {
          parse (a.value ());
        }

      private:
        void
        parse (std::basic_string<C> const& str)
        {
          // Note that according to the spec the separator is exactly
          // one space (0x20). This makes our life much easier.
          //

          for (std::size_t i (0), j (str.find (C (' ')));;)
          {
            if (j != std::basic_string<C>::npos)
            {
              push_back (idref_template<C> (str, i, j - i));
              i = j + 1;
              j = str.find (C (' '), i);
            }
            else
            {
              // Last element.
              push_back (idref_template<C> (str, i));
              break;
            }
          }
        }
      };

      template <typename C>
      inline
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, idrefs_template<C> const& r)
      {
        for (typename idrefs_template<C>::const_iterator
               b (r.begin ()), e (r.end ()), i (b); i != e; ++i)
        {
          if (i != b)
            os << C (' ');

          os << *i;
        }

        return os;
      }

      // uri
      //
      template <typename C>
      class uri_template: public std::basic_string<C>,
                          public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        uri_template ()
        {
        }

        uri_template (C* s)
            : base_type (s)
        {
        }

        uri_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        uri_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        uri_template (primary_type const& str)
            : base_type (str)
        {
        }

        uri_template (primary_type const& str,
                      std::size_t pos,
                      std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        uri_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        uri_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        uri_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        uri_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        uri_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // qname
      //
      template <typename C>
      class qname_template: public type
      {
      public:
        qname_template (uri_template<C> const& ns,
                        ncname_template<C> const& name)
            : ns_ (ns),
              name_ (name)
        {
        }
      public:
        qname_template (xml::element<C> const& e)
            : ns_ (xml::ns_name (e, e.value ())),
              name_ (xml::uq_name (e.value ()))
        {
        }

        qname_template (xml::attribute<C> const& a)
            : ns_ (xml::ns_name (a.element (), a.value ())),
              name_ (xml::uq_name (a.value ()))
        {
        }

      public:
        uri_template<C> const&
        namespace_ () const
        {
          return ns_;
        }

        ncname_template<C> const&
        name () const
        {
          return name_;
        }

      private:
        uri_template<C> ns_;
        ncname_template<C> name_;
      };

      template <typename C>
      inline
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, qname_template<C> const& n)
      {
        return os << n.namespace_ () << C ('#') << n.name ();
      }


      // base64_binary
      //
      template <typename C>
      class base64_binary_template: public std::basic_string<C>,
                                    public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        base64_binary_template ()
        {
        }

        base64_binary_template (C* s)
            : base_type (s)
        {
        }

        base64_binary_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        base64_binary_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        base64_binary_template (primary_type const& str)
            : base_type (str)
        {
        }

        base64_binary_template (primary_type const& str,
                                std::size_t pos,
                                std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        base64_binary_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        base64_binary_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        base64_binary_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        base64_binary_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        base64_binary_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // hex_binary
      //
      template <typename C>
      class hex_binary_template: public std::basic_string<C>,
                                 public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        hex_binary_template ()
        {
        }

        hex_binary_template (C* s)
            : base_type (s)
        {
        }

        hex_binary_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        hex_binary_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        hex_binary_template (primary_type const& str)
            : base_type (str)
        {
        }

        hex_binary_template (primary_type const& str,
                             std::size_t pos,
                             std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        hex_binary_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        hex_binary_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        hex_binary_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        hex_binary_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        hex_binary_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // date
      //
      template <typename C>
      class date_template: public std::basic_string<C>,
                           public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        date_template ()
        {
        }

        date_template (C* s)
            : base_type (s)
        {
        }

        date_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        date_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        date_template (primary_type const& str)
            : base_type (str)
        {
        }

        date_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        date_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        date_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        date_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        date_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        date_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };



      // date_time
      //
      template <typename C>
      class date_time_template: public std::basic_string<C>,
                                public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        date_time_template ()
        {
        }

        date_time_template (C* s)
            : base_type (s)
        {
        }

        date_time_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        date_time_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        date_time_template (primary_type const& str)
            : base_type (str)
        {
        }

        date_time_template (primary_type const& str,
                            std::size_t pos,
                            std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        date_time_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        date_time_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        date_time_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        date_time_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        date_time_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // duration
      //
      template <typename C>
      class duration_template: public std::basic_string<C>,
                               public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        duration_template ()
        {
        }

        duration_template (C* s)
            : base_type (s)
        {
        }

        duration_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        duration_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        duration_template (primary_type const& str)
            : base_type (str)
        {
        }

        duration_template (primary_type const& str,
                           std::size_t pos,
                           std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        duration_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        duration_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        duration_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        duration_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        duration_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // day
      //
      template <typename C>
      class day_template: public std::basic_string<C>,
                          public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        day_template ()
        {
        }

        day_template (C* s)
            : base_type (s)
        {
        }

        day_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        day_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        day_template (primary_type const& str)
            : base_type (str)
        {
        }

        day_template (primary_type const& str,
                      std::size_t pos,
                      std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        day_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        day_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        day_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        day_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        day_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // month
      //
      template <typename C>
      class month_template: public std::basic_string<C>,
                            public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        month_template ()
        {
        }

        month_template (C* s)
            : base_type (s)
        {
        }

        month_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        month_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        month_template (primary_type const& str)
            : base_type (str)
        {
        }

        month_template (primary_type const& str,
                        std::size_t pos,
                        std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        month_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        month_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        month_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        month_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        month_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // month_day
      //
      template <typename C>
      class month_day_template: public std::basic_string<C>,
                                public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        month_day_template ()
        {
        }

        month_day_template (C* s)
            : base_type (s)
        {
        }

        month_day_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        month_day_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        month_day_template (primary_type const& str)
            : base_type (str)
        {
        }

        month_day_template (primary_type const& str,
                            std::size_t pos,
                            std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        month_day_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        month_day_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        month_day_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        month_day_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        month_day_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // year
      //
      template <typename C>
      class year_template: public std::basic_string<C>,
                           public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        year_template ()
        {
        }

        year_template (C* s)
            : base_type (s)
        {
        }

        year_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        year_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        year_template (primary_type const& str)
            : base_type (str)
        {
        }

        year_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        year_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        year_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        year_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        year_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        year_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // year_month
      //
      template <typename C>
      class year_month_template: public std::basic_string<C>,
                                 public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        year_month_template ()
        {
        }

        year_month_template (C* s)
            : base_type (s)
        {
        }

        year_month_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        year_month_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        year_month_template (primary_type const& str)
            : base_type (str)
        {
        }

        year_month_template (primary_type const& str,
                             std::size_t pos,
                             std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        year_month_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        year_month_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        year_month_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        year_month_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        year_month_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // time
      //
      template <typename C>
      class time_template: public std::basic_string<C>,
                           public type
      {
      protected:
        typedef std::basic_string<C> primary_type;
        typedef std::basic_string<C> base_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        time_template ()
        {
        }

        time_template (C* s)
            : base_type (s)
        {
        }

        time_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        time_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        time_template (primary_type const& str)
            : base_type (str)
        {
        }

        time_template (primary_type const& str,
                       std::size_t pos,
                       std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        time_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        time_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        time_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        time_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        time_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // entity: ncname
      //
      template <typename C>
      class entity_template: public ncname_template<C>
      {
      protected:
        typedef ncname_template<C> base_type;
        typedef typename base_type::primary_type primary_type;

        base_type&
        base ()
        {
          return *this;
        }

      public:
        using base_type::npos;

      public:
        entity_template ()
        {
        }

        entity_template (C* s)
            : base_type (s)
        {
        }

        entity_template (C* s, std::size_t n)
            : base_type (s, n)
        {
        }

        entity_template (std::size_t n, C c)
            : base_type (n, c)
        {
        }

        entity_template (primary_type const& str)
            : base_type (str)
        {
        }

        entity_template (primary_type const& str,
                         std::size_t pos,
                         std::size_t n = npos)
            : base_type (str, pos, n)
        {
        }

      public:
        // Implicit copy c-tor.
        //

      public:
        entity_template (xml::element<C> const& e)
            : base_type (e.value ())
        {
        }

        entity_template (xml::attribute<C> const& a)
            : base_type (a.value ())
        {
        }

      public:
        entity_template&
        operator= (C c)
        {
          base () = c;
          return *this;
        }

        entity_template&
        operator= (C* s)
        {
          base () = s;
          return *this;
        }

        entity_template&
        operator= (primary_type const& str)
        {
          base () = str;
          return *this;
        }

        // Implicit copy assignment operator.
        //
      };


      // entities: vector<entity>
      //
      template <typename C>
      class entities_template: public vector<entity_template<C> >
      {
      public:
        entities_template (xml::element<C> const& e)
        {
          parse (e.value ());
        }

        entities_template (xml::attribute<C> const& a)
        {
          parse (a.value ());
        }

      private:
        void
        parse (std::basic_string<C> const& str)
        {
          // Note that according to the spec the separator is exactly
          // one space (0x20). This makes our life much easier.
          //

          for (std::size_t i (0), j (str.find (C (' ')));;)
          {
            if (j != std::basic_string<C>::npos)
            {
              push_back (entity_template<C> (str, i, j - i));
              i = j + 1;
              j = str.find (C (' '), i);
            }
            else
            {
              // Last element.
              push_back (entity_template<C> (str, i));
              break;
            }
          }
        }
      };

      template <typename C>
      inline
      std::basic_ostream<C>&
      operator<< (std::basic_ostream<C>& os, entities_template<C> const& en)
      {
        for (typename entities_template<C>::const_iterator
               b (en.begin ()), e (en.end ()), i (b); i != e; ++i)
        {
          if (i != b)
            os << C (' ');

          os << *i;
        }

        return os;
      }
    }
  }
}

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

#endif  // XSD_CXX_TREE_TYPES_HXX
